#ifndef OverbyteIcsThrdSrv1H
#define OverbyteIcsThrdSrv1H

#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>

#include "OverbyteIcsWSocket.hpp"
#include "OverbyteIcsWSocketS.hpp"
#include "OverbyteIcsIniFiles.hpp"
#include "OverbyteIcsTypes.hpp"
#include "OverbyteIcsWndControl.hpp"

#include <atomic>
#include <mutex>
#include <vector>

const unsigned WM_APPSTARTUP = WM_USER + 1;
const unsigned WM_LOGMSG = WM_USER + 2;

class TTcpSrvForm;

class TClientThread : public TThread
{
public:
    TClientThread(TTcpSrvForm *Form, TWSocket *WSocket);
    __fastcall ~TClientThread();
    void Display(const String &Msg);
    void RequestStop();
    bool WaitForStop(DWORD TimeoutMs);
    std::atomic<bool> ThreadAttached;

protected:
    void __fastcall Execute() override;

private:
    TTcpSrvForm *FForm;
    TWSocket *FWSocket;
    HANDLE FStopEvent;
};

class TThrdSrvClient : public TWSocketClient
{
public:
    __fastcall virtual TThrdSrvClient(TComponent *AOwner) : TWSocketClient(AOwner) {}
    __fastcall virtual ~TThrdSrvClient();
    void StopThread();
    TClientThread *ClientThread = nullptr;
    String RcvdLine;
    TDateTime ConnectTime;
};

struct TWhoEntry
{
    TObject *Client;
    String Addr;
    String Port;
    TDateTime ConnectTime;
};

class TTcpSrvForm : public TForm
{
__published:
    TPanel *ToolPanel;
    TMemo *DisplayMemo;
    TWSocketServer *WSocketServer1;
    void __fastcall FormShow(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall WSocketServer1ClientConnect(TObject *Sender, TWSocketClient *Client, System::Word Error);
    void __fastcall WSocketServer1ClientDisconnect(TObject *Sender, TWSocketClient *Client, System::Word Error);
    void __fastcall WSocketServer1BgException(TObject *Sender, Exception *E, bool &CanClose);
    void __fastcall WSocketServer1ClientCreate(TObject *Sender, TWSocketClient *Client);

protected:
    void __fastcall WmLogMessage(TMessage &Msg);
    void __fastcall WMAppStartup(TMessage &Msg);

    BEGIN_MESSAGE_MAP
        VCL_MESSAGE_HANDLER(WM_LOGMSG, TMessage, WmLogMessage)
        VCL_MESSAGE_HANDLER(WM_APPSTARTUP, TMessage, WMAppStartup)
    END_MESSAGE_MAP(TForm)

private:
    String FIniFileName;
    bool FInitialized = false;
    std::mutex FLogMutex;
    std::vector<String> FLogList;
    std::mutex FWhoMutex;
    std::vector<TWhoEntry> FWho;

    void Display(const String &Msg);
    void __fastcall ClientDataAvailable(TObject *Sender, System::Word Error);
    void ProcessData(TThrdSrvClient *Client);
    void __fastcall ClientBgException(TObject *Sender, Exception *E, bool &CanClose);
    void __fastcall ClientLineLimitExceeded(TObject *Sender, int Cnt, bool &ClearData);

public:
    __fastcall TTcpSrvForm(TComponent *Owner);
    __fastcall ~TTcpSrvForm();
    void QueueLog(const String &Msg);
    __property String IniFileName = {read = FIniFileName, write = FIniFileName};
};

extern PACKAGE TTcpSrvForm *TcpSrvForm;

#endif
