#ifndef BASIC_API_HPP
#define BASIC_API_HPP

#include "src/PassiveSocket.h"
#include "picofunctions.h"
#include "pugiconfig.hpp"
#include "pugixml.hpp"
#include "msgpack.hpp"
#include "src/simplelogger.hpp"
#include <vector>
#include <iostream>
#include <functional>

#define MAX_PACKET 4096
#define CMD_CLOSE 0x01

inline std::ostream& hex_dump(std::ostream& o, std::string const& v) {
    std::ios::fmtflags f(o.flags());
    o << std::hex;
    for (auto c : v) {
        o << "0x" << std::setw(2) << std::setfill('0') << (static_cast<int>(c) & 0xff) << ' ';
    }
    o.flags(f);
    return o;
}

class basic_proto_dispatcher {
    protected:
        CActiveSocket* SocketActive;
        uint8_t magic_number = 0xAA;
        uint8_t command_code = 0x00;
        std::map<uint8_t, std::function<int()>> command_callbacks;

        std::uint32_t error_code = 0x00000000;
        std::uint32_t status_code = 0x00000000;
        std::uint32_t nbytes_sent = 0;

        uint8_t* rcbuf;

        msgpack::sbuffer* sbuff_ptr;
        msgpack::packer<msgpack::sbuffer>* pk_ptr;
        msgpack::unpacker* upk_ptr;

    public:
        basic_proto_dispatcher(CActiveSocket* sock);

        int changeSocket(CActiveSocket* sock);
        int setMagicNumber(uint8_t magic);
        int configureMsgpack(msgpack::sbuffer* sbuff_ptr, msgpack::packer<msgpack::sbuffer>* pk_ptr, msgpack::unpacker* upk_ptr);

        std::uint32_t getErrorCode();
        std::uint32_t getStatusCode();
        uint8_t getLastCommand();
        std::uint32_t getNbytesSent();

        virtual int sendErrorMsg(std::uint32_t errCode, std::string errStr);
        virtual int sendStatusMsg(std::uint32_t statCode, std::string statStr);
        
        virtual int recvValidatedHeader();
        virtual int sendValidatedMsgpackData();
        virtual int stopSession();

        virtual int acceptRequest();
};

#endif