#pragma once

#include <thread>
#include <atomic>
#include <string>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "ssl.h"
#include <nerutils/callback.h>

/*
    TO-DO:
        use random port, test availability
*/
#define PROXY_PORT 58421
#define PROXY_THREAD_COUNT 32

typedef unsigned __int64 SOCKET;

class Proxy
{
    public:
        Proxy();
        ~Proxy();

        bool init();
        void shutdown();

        CallbackEvent<std::string&, const std::string&, std::string&> OnClientRequest;
        CallbackEvent<const std::string&, std::string&, std::string&> OnServerResponse;

    private:
        void loop();
        void handleClient(SOCKET clientSocket);

        bool initSSL();
        void cleanupSSL();

        SOCKET _listenSocket = 0;
        std::thread _workerThread;
        std::atomic<bool> _running = false;

        std::vector<std::thread> _poolThreads;
        std::queue<SOCKET> _clientQueue;
        std::mutex _queueMutex;
        std::condition_variable _queueCond;

        CertManager _certManager;
        SSL_CTX* _clientCtx = nullptr;
};
