#pragma once

#include <iostream>
#include <functional>
#include <vector>
#include <memory>
#include <mutex>
#include <thread>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <poll.h>
#include <string>
#include <algorithm>
#include <exception>

class LFR_Socket
{
public:
    using LFR_Telegram = char[1024];
    using ListenerKey = void const*;
    using ExceptionCallback = std::function<bool(std::exception const &ex)>;
    using ListenerCallback = std::function<void(LFR_Telegram)>;
private:
    using ListenerPair = std::pair<ListenerKey, ListenerCallback>;
    using ListenerVector = std::vector<ListenerPair>;

    ListenerVector listeners;
    ExceptionCallback cb;
    bool stop;
    std::unique_ptr<std::thread> thread;
    mutable std::mutex mutex;

    int server_fd, new_socket, bytes_received;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};    

    
    //void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi);
    void createThread();
    void setStop(bool val);

public:
    LFR_Socket() = delete;
    LFR_Socket(ExceptionCallback cb);
    ~LFR_Socket();

    void startLoop();
    void endLoop();
    void addListener(ListenerCallback cv, ListenerKey key);
    void removeListener(ListenerKey key);
    void isStopped() const noexcept;
    //const bool interpretMessage(co)
};