#ifndef OverbyteIcsSslMultiWebServ1H
#define OverbyteIcsSslMultiWebServ1H

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

#include "OverbyteIcsTypes.hpp"
#include "OverbyteIcsSslBase.hpp"
#include "OverbyteIcsWSocket.hpp"
#include "OverbyteIcsWSocketS.hpp"
#include "OverbyteIcsHttpSrv.hpp"
#include "OverbyteIcsHttpAppServer.hpp"
#include "OverbyteIcsWebSession.hpp"
#include "OverbyteIcsWebSocketCli.hpp"
#include "OverbyteIcsWebSocketSrv.hpp"
#include "OverbyteIcsSslX509Certs.hpp"
#include "OverbyteIcsMailQueue.hpp"
#include "OverbyteIcsSslHttpOAuth.hpp"
#include "OverbyteIcsDnsQuery.hpp"
#include "OverbyteIcsBlacklist.hpp"
#include "OverbyteIcsSslUtils.hpp"
#include "IcsGeoUtils.hpp"
#include "OverbyteIcsSslMultiWebPages.h"
#include "OverbyteIcsWndControl.hpp"

#include <memory>
#include <vector>

const unsigned WM_STARTUP = WM_USER + 712;

class TMyHttpConnection : public THttpWSSrvConn
{
    typedef THttpWSSrvConn inherited;
public:
    __int64 CStartTick = 0;
    String CPeerHostName;
    __int64 CLastRead = 0;
    __int64 CLastWrite = 0;
    using THttpConnection::AuthGetMethod;
    using THttpConnection::Answer404;
    __fastcall virtual TMyHttpConnection(TComponent *AOwner);
    void __fastcall BgExceptionEvent(TObject *Sender, Exception *E, bool &CanClose);
    void SetPeerHostName(const String &HostName);
};

class TWeblServerForm : public TForm
{
__published:
    TPanel *Panel1;
    TButton *StopButton;
    TButton *StartButton;
    TButton *doClear;
    TButton *RecheckCertsButton;
    TCheckBox *DisplayHeaderCheckBox;
    TCheckBox *DisplaySslInfo;
    TMemo *DisplayMemo;
    TIcsMailQueue *IcsMailQueue;
    TSslX509Certs *IcsSslX509Certs;
    TTimer *Timer1;
    TSslHttpAppSrv *SslHttpAppSrv1;
    TIcsRestEmail *IcsRestEmail;
    TIcsDomainNameCache *IcsDomainNameCache1;
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall StartButtonClick(TObject *Sender);
    void __fastcall StopButtonClick(TObject *Sender);
    void __fastcall Timer1Timer(TObject *Sender);
    void __fastcall RecheckCertsButtonClick(TObject *Sender);
    void __fastcall DisplayHeaderCheckBoxClick(TObject *Sender);
    void __fastcall SslHttpAppSrv1ClientConnect(TObject *Sender, TObject *Client, System::Word Error);
    void __fastcall SslHttpAppSrv1ServerStarted(TObject *Sender);
    void __fastcall SslHttpAppSrv1ServerStopped(TObject *Sender);
    void __fastcall SslHttpAppSrv1WellKnownDir(TObject *Sender, TObject *Client, const String Path, String &BodyStr);
    void __fastcall SslHttpAppSrv1DeleteSession(TObject *Sender, TIcsWebSession *Session);
    void __fastcall SslHttpAppSrv1GetDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1AfterAnswer(TObject *Sender, TObject *Client);
    void __fastcall SslHttpAppSrv1BeforeProcessRequest(TObject *Sender, TObject *Client);
    void __fastcall SslHttpAppSrv1VirtualException(TObject *Sender, Exception *E, THttpMethod Method, const String Path);
    void __fastcall SslHttpAppSrv1SslHandshakeDone(TObject *Sender, System::Word ErrCode, TX509Base *PeerCert, bool &Disconnect);
    void __fastcall SslHttpAppSrv1BgException(TObject *Sender, Exception *E, bool &CanClose);
    void __fastcall SslHttpAppSrv1Display(TObject *Sender, const String Msg);
    void __fastcall SslHttpAppSrv1HeadDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1HttpMimeContentType(TObject *Sender, TObject *Client, const String FileName, String &ContentType);
    void __fastcall SslHttpAppSrv1DeleteDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1PatchDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1PutDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1AuthGetType(TObject *Sender, TObject *Client);
    void __fastcall SslHttpAppSrv1AuthGetPassword(TObject *Sender, TObject *Client, String &Password);
    void __fastcall SslHttpAppSrv1AuthResult(TObject *Sender, TObject *Client, bool Success);
    void __fastcall SslHttpAppSrv1AuthNtlmBeforeValidate(TObject *Sender, TObject *Client, bool &Allow);
    void __fastcall SslHttpAppSrv1PostDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1QueryDocument(TObject *Sender, TObject *Client, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1HttpRequestDone(TObject *Sender, TObject *Client);
    void __fastcall SslHttpAppSrv1PostedData(TObject *Sender, TObject *Client, System::Word Error);
    void __fastcall SslHttpAppSrv1HttpCustomError(TObject *Sender, TObject *Client, int ErrNr, const String Info, String &Body);
    void __fastcall SslHttpAppSrv1HttpAcceptFilter(TObject *Sender, TObject *Client, TIcsSessIpInfo &SessIpInfo, bool &Allowed);
    void __fastcall SslHttpAppSrv1WebDAVDocument(TObject *Sender, TObject *Client, THttpMethod HttpMethod, THttpGetFlag &Flags);
    void __fastcall SslHttpAppSrv1SslAlpnSelect(TObject *Sender, TStrings *ProtoList, String &SelProto, TTlsExtError &ErrCode);
    void __fastcall SslHttpAppSrv1SslServerName(TObject *Sender, TSslContext *&Ctx, TTlsExtError &ErrCode);
    void __fastcall IcsSslX509CertsCertProg(TObject *Sender, TLogOption LogOption, const String Msg);
    void __fastcall IcsSslX509CertsNewCert(TObject *Sender);
    void __fastcall IcsSslX509CertsOAuthAuthUrl(TObject *Sender, const String URL);
    void __fastcall IcsSslX509CertsChallengeDNS(TObject *Sender, const TChallengeItem &ChallengeItem, bool &ChlgOK);
    void __fastcall IcsSslX509CertsChallgRefresh(TObject *Sender);
    void __fastcall IcsSslX509CertsGeoEvent(TObject *Sender, const String IpStr, String &Geo);
    void __fastcall IcsMailQueueLogEvent(TMailLogLevel LogLevel, const String Info);
    void __fastcall IcsMailQueueOATokenEvent(int ServNr, String &Token, String &TokAccount, TDateTime &TokExpireDT);
    void __fastcall IcsRestEmailEmailNewToken(TObject *Sender);
    void __fastcall IcsRestEmailEmailProg(TObject *Sender, TLogOption LogOption, const String Msg);
    void __fastcall IcsDomainNameCache1DNUpdateEvent(TObject *Sender, int ItemNr);
    void __fastcall IcsDomainNameCache1GeoEvent(TObject *Sender, const String IpStr, String &Geo);
    void __fastcall IcsAppLog(TObject *Sender, const String Msg);
public:
    void __fastcall ClientWSLogEvent(TObject *Sender, const String Msg);
    void __fastcall ClientWSHandshakeEvent(THttpWSSrvConn *Client, bool &OK, String &WelcomeMsg);
    void __fastcall ClientWSFrameRcvdEvent(THttpWSSrvConn *Client, const String APacket, TWebSocketReceivedFrame *&AFrame);
    void __fastcall ClientWSFrameSentEvent(THttpWSSrvConn *Client, TWebSocketOutgoingFrame *&AFrame);
    void __fastcall ClientWSDisconnectedEvent(TObject *Sender);
    void __fastcall ClientWSReadyEvent(THttpWSSrvConn *Client);
    void __fastcall ClientWSPingTimerEvent(THttpWSSrvConn *Client);
    void Display(const String &Msg);
    void ReportHosts();
    const String &ServerInfo() const { return FServerInfo; }
    __fastcall TWeblServerForm(TComponent *Owner);
    __fastcall virtual ~TWeblServerForm();
private:
    TSslMultiWebDataModule FPagesData;
    String FWinLinesBuff;
    String FSrvCompName;
    std::unique_ptr<TIcsBuffLogStream> FDiagLogBuffer;
    std::vector<std::unique_ptr<TIcsBuffLogStream>> FWebLogBuffers;
    String FIniFileName;
    bool FFinalized = false;
    String FBaseDir;
    String FDataDir;
    String FUploadsDir;
    String FSessionFile;
    String FServerInfo;
    int FWinDispCur = 0;
    int FLogDate = 0;
    String FStatSrvSslCert;
    String FStatSrvSslCertWeb;
    __int64 FHouseKeepingTrg = 0;
    __int64 FCertCheckTrigger = 0;
    String FAdminEmailTo;
    String FAdminEmailFrom;
    String FLastErrorEmail;
    String FOldRefrToken;
    bool FChallengeTestingActive = false;
    std::unique_ptr<TIcsBlacklist> FAttemptsBlackList;
    std::unique_ptr<TIcsBlacklist> FHackBlackList;
    std::unique_ptr<TIcsFilterList> FFilterList;
    std::unique_ptr<TIcsIpAddrList> FWhiteList;
    std::unique_ptr<TIcsGeoTools> FGeoTools;
    void __fastcall WMStartup(TMessage &Msg);
    void __fastcall ApplicationEventsException(TObject *Sender, Exception *E);
    void __fastcall HttpAppSrvClientBgException(TObject *Sender, Exception *E, bool &CanClose);
    void __fastcall doClearClick(TObject *Sender);
    void __fastcall CountryNameEvent(TObject *Sender, const String ISOA2, String &CountryName);
    String GeoForIp(const String &IpStr);
    void StartQueueMail();
    void StopQueueMail();
    void SendAdminEmail(const String &EmailTo, const String &Subject, const String &Body);
    void LoadHackLists();
    bool TestDottedIp(const String &Value);
    void FlushDiagLog();
    String BuildDemoURIs();
    void WSSendChatResp(THttpWSSrvConn *SendCli, const String &APacket, bool ToMe);
    int WSGetChatUsers(const String &ChatPage, String &UList);
    void CreateVirtualDocument_Demo(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_DemoBasicAuth(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_DemoDigestAuth(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_DemoDigest2Auth(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_DemoDigestsAll(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_DemoNtlmAuth(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_Time(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_Bruno(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_Redir(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_MyIP(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_HeaderBug(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);
    void CreateVirtualDocument_Template(TMyHttpConnection *ClientCnx, THttpGetFlag &Flags);

    BEGIN_MESSAGE_MAP
        VCL_MESSAGE_HANDLER(WM_STARTUP, TMessage, WMStartup)
    END_MESSAGE_MAP(TForm)
};

extern PACKAGE TWeblServerForm *WeblServerForm;

#endif
