#ifndef OverbyteIcsSslFtpServ1H
#define OverbyteIcsSslFtpServ1H

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

#include "OverbyteIcsWSocket.hpp"
#include "OverbyteIcsWSocketS.hpp"
#include "OverbyteIcsWndControl.hpp"
#include "OverbyteIcsFtpSrv.hpp"
#include "OverbyteIcsOneTimePw.hpp"
#include "OverbyteIcsSslBase.hpp"
#include "OverbyteIcsTypes.hpp"
#include <Vcl.Graphics.hpp>

const int WM_APPSTARTUP = WM_USER + 1;

class TGetProcessingThread;

class TMyClient : public TFtpCtrlSocket
{
public:
    TGetProcessingThread *FWorkerThread = nullptr;
    bool FWorkerCancelled = false;
    unsigned __int64 LastSslHandshake = 0;
    __fastcall virtual TMyClient(TComponent *AOwner) : TFtpCtrlSocket(AOwner) {}
    __fastcall virtual ~TMyClient();
};

class TGetProcessingThread : public TThread
{
public:
    TFtpServer *Server = nullptr;
    TMyClient *Client = nullptr;
    __fastcall TGetProcessingThread() : TThread(true) {}
protected:
    void __fastcall Execute() override;
};

class TSslFtpServerForm : public TForm
{
__published:
    TSslFtpServer *SslFtpServer1;
    TMemo *InfoMemo;
    TPanel *Panel1;
    TCheckBox *StartMinimizedCheckBox;
    TMainMenu *MainMenu1;
    TMenuItem *File1;
    TMenuItem *MnuStartServer;
    TMenuItem *MnuStopServer;
    TMenuItem *MnuQuit;
    TMenuItem *N1;
    TImage *GreenImage;
    TLabel *ClientCountLabel;
    TImage *RedImage;
    TMenuItem *Tools1;
    TMenuItem *Cleardisplay1;
    TMenuItem *MnuListClients;
    TMenuItem *N2;
    TMenuItem *DisconnectAllMnu;
    TSslContext *SslContext1;
    TEdit *CertFileEdit;
    TLabel *Label4;
    TLabel *Label6;
    TEdit *PrivKeyFileEdit;
    TLabel *Label7;
    TEdit *PassPhraseEdit;
    TLabel *Label11;
    TEdit *CAFileEdit;
    TLabel *Label10;
    TEdit *CAPathEdit;
    TCheckBox *VerifyPeerCheckBox;
    TEdit *SslTypeConnPortEdit;
    TLabel *Label1;
    TSslFtpServer *SslFtpServer2;
    TLabel *Label17;
    TEdit *RenegotiationIntervalEdit;
    TLabel *Label18;
    TLabel *Label16;
    TCheckBox *DisplaySslInfoCheckBox;
    TLabel *Label2;
    TEdit *ServIpAddr;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormShow(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall SslFtpServer1ClientConnect(TObject *Sender, TFtpCtrlSocket *Client, System::Word AError);
    void __fastcall SslFtpServer1ClientDisconnect(TObject *Sender, TFtpCtrlSocket *Client, System::Word AError);
    void __fastcall SslFtpServer1Start(TObject *Sender);
    void __fastcall SslFtpServer1Stop(TObject *Sender);
    void __fastcall SslFtpServer1ClientCommand(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &Keyword,
                                               TFtpString &Params, TFtpString &Answer);
    void __fastcall SslFtpServer1StorSessionConnected(TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data,
                                                      System::Word AError);
    void __fastcall SslFtpServer1StorSessionClosed(TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data,
                                                   System::Word AError);
    void __fastcall SslFtpServer1RetrDataSent(TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data,
                                              System::Word AError);
    void __fastcall SslFtpServer1RetrSessionConnected(TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data,
                                                      System::Word AError);
    void __fastcall SslFtpServer1RetrSessionClosed(TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data,
                                                   System::Word AError);
    void __fastcall SslFtpServer1AnswerToClient(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &Answer);
    void __fastcall SslFtpServer1Authenticate(TObject *Sender, TFtpCtrlSocket *Client, TFtpString UserName,
                                              TFtpString Password, bool &Authenticated);
    void __fastcall MnuQuitClick(TObject *Sender);
    void __fastcall MnuStopServerClick(TObject *Sender);
    void __fastcall MnuStartServerClick(TObject *Sender);
    void __fastcall ImagesDblClick(TObject *Sender);
    void __fastcall SslFtpServer1BuildDirectory(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &Directory,
                                                bool Detailed);
    void __fastcall SslFtpServer1AlterDirectory(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &Directory,
                                                bool Detailed);
    void __fastcall Cleardisplay1Click(TObject *Sender);
    void __fastcall MnuListClientsClick(TObject *Sender);
    void __fastcall DisconnectAllMnuClick(TObject *Sender);
    void __fastcall SslFtpServer1GetProcessing(TObject *Sender, TFtpCtrlSocket *Client, bool &DelayedSend);
    void __fastcall SslFtpServer1SslVerifyPeer(TObject *Sender, int &Ok, TX509Base *Cert);
    void __fastcall SslFtpServer1SslHandshakeDone(TObject *Sender, System::Word ErrCode, TX509Base *PeerCert,
                                                  bool &Disconnect);
    void __fastcall RenegotiationIntervalEditChange(TObject *Sender);
    void __fastcall SslFtpServer1OtpGetPassword(TObject *Sender, TFtpCtrlSocket *Client, TFtpString UserName,
                                                String &UserPassword);
    void __fastcall SslFtpServer1OtpMethod(TObject *Sender, TFtpCtrlSocket *Client, TFtpString UserName,
                                           TOtpMethod &OtpMethod);
    void __fastcall SslFtpServer1ValidateDele(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &FilePath,
                                              bool &Allowed);
    void __fastcall SslFtpServer1ValidatePut(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &FilePath,
                                             bool &Allowed);
    void __fastcall SslFtpServer1ValidateRnFr(TObject *Sender, TFtpCtrlSocket *Client, TFtpString &FilePath,
                                              bool &Allowed);
    void __fastcall SslFtpServer1MakeDirectory(TObject *Sender, TFtpCtrlSocket *Client, TFtpString Directory,
                                               bool &Allowed);
    void __fastcall SslFtpServer1Host(TObject *Sender, TFtpCtrlSocket *Client, TFtpString Host, bool &Allowed);
    void __fastcall SslFtpServer1Rein(TObject *Sender, TFtpCtrlSocket *Client, bool &Allowed);
    void __fastcall SslFtpServer1Display(TObject *Sender, TFtpCtrlSocket *Client, TFtpString Msg);

private:
    bool FInitialized = false;
    String FIniFileName;
    String FPort;
    int FXTop = 0;
    int FXLeft = 0;
    int FXWidth = 0;
    int FXHeight = 0;
    unsigned FSslRenegotiationInterval = 0;
    int FOtpSequence = 0;
    String FOtpSeed;
    String FAccountDir;
    void __fastcall WorkerThreadTerminated(TObject *Sender);
    void __fastcall WMAppStartup(TMessage &Msg);
    void Display(const String &Msg);
    void CheckRenegotiation(TMyClient *Client, bool IsData);
    void LoadConfig();
    void SaveConfig();
    void StartServer();
    void StopServer();
    void UpdateClientCount(int Leaving = 0);
    void SetDefaultAccount(TFtpCtrlSocket *Client);

public:
    __fastcall TSslFtpServerForm(TComponent *Owner);
    __fastcall virtual ~TSslFtpServerForm();

BEGIN_MESSAGE_MAP
    VCL_MESSAGE_HANDLER(WM_APPSTARTUP, TMessage, WMAppStartup)
END_MESSAGE_MAP(TForm)
};

extern PACKAGE TSslFtpServerForm *SslFtpServerForm;

#endif
