#ifndef WEBSOCKETSESSION_H
#define WEBSOCKETSESSION_H

#include "BoostLog.h"
#include "SharedState.h"
#include <boost/beast.hpp>
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>

class SharedState;

/**
 * @brief Represents an active WebSocket connection to the server
 */
class WebSocketSession : public std::enable_shared_from_this<WebSocketSession> {

public:
    WebSocketSession(boost::asio::ip::tcp::socket &&socket, std::shared_ptr<SharedState> const &state);

    ~WebSocketSession();

    template <class Body, class Allocator>
    void run(boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>> request) {
        using namespace boost::beast::http;
        using namespace boost::beast::websocket;
        // Set suggested timeout settings for the websocket
        m_ws.set_option(stream_base::timeout::suggested(boost::beast::role_type::server));

        // Set a decorator to change the Server of the handshake
        m_ws.set_option(stream_base::decorator([](response_type &response) {
            response.set(field::server, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-chat-multi");
        }));
        // LOG(info) << request.base().target(); //get path
        // Accept the websocket handshake
        m_ws.async_accept(request, [self{shared_from_this()}](boost::beast::error_code ec) { self->onAccept(ec); });
    }

    // Send a message
    void send(std::shared_ptr<std::string const> const &ss);

protected:
    void onAccept(boost::beast::error_code ec);
    void on_read(boost::beast::error_code ec, std::size_t bytes_transferred);
    void on_write(boost::beast::error_code ec, std::size_t bytes_transferred);
    void onSend(std::shared_ptr<std::string const> const &ss);

private:
    boost::beast::flat_buffer m_buffer;
    boost::beast::websocket::stream<boost::beast::tcp_stream> m_ws;
    std::shared_ptr<SharedState> m_state;
    std::vector<std::shared_ptr<std::string const>> m_queue;
};

#endif // WEBSOCKETSESSION_H
