// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once
#include "bmcweb_config.h"

#include "boost_formatters.hpp"
#include "http_body.hpp"
#include "http_request.hpp"
#include "logging.hpp"
#include "ossl_random.hpp"
#include "sessions.hpp"
#include "websocket.hpp"

#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/beast/core/role.hpp>
#include <boost/beast/http/field.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/websocket/error.hpp>
#include <boost/beast/websocket/rfc6455.hpp>
#include <boost/beast/websocket/stream.hpp>
#include <boost/beast/websocket/stream_base.hpp>
#include <boost/url/url_view.hpp>

// NOLINTNEXTLINE(misc-include-cleaner)
#include <boost/beast/websocket/ssl.hpp>

#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>

namespace crow
{
namespace websocket
{

template <typename Adaptor>
class ConnectionImpl : public Connection
{
    using self_t = ConnectionImpl<Adaptor>;

  public:
    ConnectionImpl(
        const boost::urls::url_view& urlViewIn,
        const std::shared_ptr<persistent_data::UserSession>& sessionIn,
        Adaptor adaptorIn, std::function<void(Connection&)> openHandlerIn,
        std::function<void(Connection&, const std::string&, bool)>
            messageHandlerIn,
        std::function<void(crow::websocket::Connection&, std::string_view,
                           crow::websocket::MessageType type,
                           std::function<void()>&& whenComplete)>
            messageExHandlerIn,
        std::function<void(Connection&, const std::string&)> closeHandlerIn,
        std::function<void(Connection&)> errorHandlerIn) :
        uri(urlViewIn), ws(std::move(adaptorIn)), inBuffer(inString, 131088),
        openHandler(std::move(openHandlerIn)),
        messageHandler(std::move(messageHandlerIn)),
        messageExHandler(std::move(messageExHandlerIn)),
        closeHandler(std::move(closeHandlerIn)),
        errorHandler(std::move(errorHandlerIn)), session(sessionIn)
    {
        /* Turn on the timeouts on websocket stream to server role */
        ws.set_option(boost::beast::websocket::stream_base::timeout::suggested(
            boost::beast::role_type::server));
        BMCWEB_LOG_DEBUG("Creating new connection {}", logPtr(this));
    }

    void start(const crow::Request& req)
    {
        BMCWEB_LOG_DEBUG("starting connection {}", logPtr(this));

        using bf = boost::beast::http::field;
        std::string protocolHeader{
            req.getHeaderValue(bf::sec_websocket_protocol)};

        ws.set_option(boost::beast::websocket::stream_base::decorator(
            [session{session},
             protocolHeader](boost::beast::websocket::response_type& m) {
                if constexpr (!BMCWEB_INSECURE_DISABLE_CSRF)
                {
                    if (session != nullptr)
                    {
                        // use protocol for csrf checking
                        if (session->cookieAuth &&
                            !bmcweb::constantTimeStringCompare(
                                protocolHeader, session->csrfToken))
                        {
                            BMCWEB_LOG_ERROR("Websocket CSRF error");
                            m.result(boost::beast::http::status::unauthorized);
                            return;
                        }
                    }
                }
                if (!protocolHeader.empty())
                {
                    m.insert(bf::sec_websocket_protocol, protocolHeader);
                }

                m.insert(bf::strict_transport_security,
                         "max-age=31536000; "
                         "includeSubdomains; "
                         "preload");
                m.insert(bf::pragma, "no-cache");
                m.insert(bf::cache_control, "no-Store,no-Cache");
                m.insert("Content-Security-Policy", "default-src 'self'");
                m.insert("X-XSS-Protection", "1; "
                                             "mode=block");
                m.insert("X-Content-Type-Options", "nosniff");
            }));

        // Make a pointer to keep the req alive while we accept it.
        using Body = boost::beast::http::request<bmcweb::HttpBody>;
        std::unique_ptr<Body> mobile = std::make_unique<Body>(req.req);
        Body* ptr = mobile.get();
        // Perform the websocket upgrade
        ws.async_accept(*ptr,
                        std::bind_front(&self_t::acceptDone, this,
                                        shared_from_this(), std::move(mobile)));
    }

    void sendBinary(std::string_view msg) override
    {
        ws.binary(true);
        outBuffer.commit(boost::asio::buffer_copy(outBuffer.prepare(msg.size()),
                                                  boost::asio::buffer(msg)));
        doWrite();
    }

    void sendEx(MessageType type, std::string_view msg,
                std::function<void()>&& onDone) override
    {
        if (doingWrite)
        {
            BMCWEB_LOG_CRITICAL(
                "Cannot mix sendEx usage with sendBinary or sendText");
            onDone();
            return;
        }
        ws.binary(type == MessageType::Binary);

        ws.async_write(boost::asio::buffer(msg),
                       [weak(weak_from_this()), onDone{std::move(onDone)}](
                           const boost::beast::error_code& ec, size_t) {
                           std::shared_ptr<Connection> self = weak.lock();
                           if (!self)
                           {
                               BMCWEB_LOG_ERROR("Connection went away");
                               return;
                           }

                           // Call the done handler regardless of whether we
                           // errored, but before we close things out
                           onDone();

                           if (ec)
                           {
                               BMCWEB_LOG_ERROR("Error in ws.async_write {}",
                                                ec);
                               self->close("write error");
                           }
                       });
    }

    void sendText(std::string_view msg) override
    {
        ws.text(true);
        outBuffer.commit(boost::asio::buffer_copy(outBuffer.prepare(msg.size()),
                                                  boost::asio::buffer(msg)));
        doWrite();
    }

    void close(std::string_view msg) override
    {
        ws.async_close(
            {boost::beast::websocket::close_code::normal, msg},
            [self(shared_from_this())](const boost::system::error_code& ec) {
                if (ec == boost::asio::error::operation_aborted)
                {
                    return;
                }
                if (ec)
                {
                    BMCWEB_LOG_ERROR("Error closing websocket {}", ec);
                    return;
                }
            });
    }

    boost::urls::url_view url() override
    {
        return uri;
    }

    void acceptDone(const std::shared_ptr<Connection>& /*self*/,
                    const std::unique_ptr<
                        boost::beast::http::request<bmcweb::HttpBody>>& /*req*/,
                    const boost::system::error_code& ec)
    {
        if (ec)
        {
            BMCWEB_LOG_ERROR("Error in ws.async_accept {}", ec);
            return;
        }
        BMCWEB_LOG_DEBUG("Websocket accepted connection");

        if (openHandler)
        {
            openHandler(*this);
        }
        doRead();
    }

    void deferRead() override
    {
        readingDefered = true;

        // If we're not actively reading, we need to take ownership of
        // ourselves for a small portion of time, do that, and clear when we
        // resume.
        selfOwned = shared_from_this();
    }

    void resumeRead() override
    {
        readingDefered = false;
        doRead();

        // No longer need to keep ourselves alive now that read is active.
        selfOwned.reset();
    }

    void afterRead(const std::shared_ptr<Connection>& /*self*/,
                   const boost::beast::error_code& ec, size_t bytesRead)
    {
        if (ec)
        {
            if (ec == boost::beast::error::timeout)
            {
                BMCWEB_LOG_WARNING("doRead timeout: {}", ec);
            }
            else if (ec != boost::beast::websocket::error::closed &&
                     ec != boost::asio::error::eof &&
                     ec != boost::asio::ssl::error::stream_truncated)
            {
                BMCWEB_LOG_ERROR("doRead error {}", ec);
            }
            if (closeHandler)
            {
                std::string reason{ws.reason().reason.c_str()};
                closeHandler(*this, reason);
            }
            return;
        }

        handleMessage(bytesRead);
    }

    void doRead()
    {
        if (readingDefered)
        {
            return;
        }
        ws.async_read(inBuffer, std::bind_front(&self_t::afterRead, this,
                                                shared_from_this()));
    }

    void afterWrite(const std::shared_ptr<Connection>& /*self*/,
                    const boost::beast::error_code& ec, size_t bytesSent)
    {
        doingWrite = false;
        outBuffer.consume(bytesSent);
        if (ec == boost::beast::websocket::error::closed)
        {
            // Do nothing here.  doRead handler will call the
            // closeHandler.
            close("Write error");
            return;
        }
        if (ec)
        {
            BMCWEB_LOG_ERROR("Error in ws.async_write {}", ec);
            return;
        }
        doWrite();
    }

    void doWrite()
    {
        // If we're already doing a write, ignore the request, it will be picked
        // up when the current write is complete
        if (doingWrite)
        {
            return;
        }

        if (outBuffer.size() == 0)
        {
            // Done for now
            return;
        }
        doingWrite = true;
        ws.async_write(
            outBuffer.data(),
            std::bind_front(&self_t::afterWrite, this, shared_from_this()));
    }

  private:
    void handleMessage(size_t bytesRead)
    {
        if (messageExHandler)
        {
            // Note, because of the interactions with the read buffers,
            // this message handler overrides the normal message handler
            messageExHandler(*this, inString, MessageType::Binary,
                             [this, self(shared_from_this()), bytesRead]() {
                                 if (self == nullptr)
                                 {
                                     return;
                                 }

                                 inBuffer.consume(bytesRead);
                                 inString.clear();

                                 doRead();
                             });
            return;
        }

        if (messageHandler)
        {
            messageHandler(*this, inString, ws.got_text());
        }
        inBuffer.consume(bytesRead);
        inString.clear();
        doRead();
    }

    boost::urls::url uri;

    boost::beast::websocket::stream<Adaptor, false> ws;

    bool readingDefered = false;
    std::string inString;
    boost::asio::dynamic_string_buffer<std::string::value_type,
                                       std::string::traits_type,
                                       std::string::allocator_type>
        inBuffer;

    boost::beast::multi_buffer outBuffer;
    bool doingWrite = false;

    std::function<void(Connection&)> openHandler;
    std::function<void(Connection&, const std::string&, bool)> messageHandler;
    std::function<void(crow::websocket::Connection&, std::string_view,
                       crow::websocket::MessageType type,
                       std::function<void()>&& whenComplete)>
        messageExHandler;
    std::function<void(Connection&, const std::string&)> closeHandler;
    std::function<void(Connection&)> errorHandler;
    std::shared_ptr<persistent_data::UserSession> session;

    std::shared_ptr<Connection> selfOwned;
};
} // namespace websocket
} // namespace crow
