#ifndef OverbyteIcsSslMultiWebPagesH
#define OverbyteIcsSslMultiWebPagesH

#include <System.Classes.hpp>
#include <System.SysUtils.hpp>

#include "OverbyteIcsTypes.hpp"
#include "OverbyteIcsWSocket.hpp"
#include "OverbyteIcsWndControl.hpp"
#include "OverbyteIcsHttpSrv.hpp"
#include "OverbyteIcsHttpAppServer.hpp"
#include "OverbyteIcsWebSession.hpp"
#include "OverbyteIcsSslHttpRest.hpp"
#include "OverbyteIcsMailQueue.hpp"
#include "IcsGeoUtils.hpp"

#include <memory>

extern const wchar_t *const UrlLogin;
extern const wchar_t *const UrlDoLoginSecure;
extern const wchar_t *const UrlHomePage;
extern const wchar_t *const UrlCounter;
extern const wchar_t *const UrlConfigForm;
extern const wchar_t *const UrlDoConfigHtml;
extern const wchar_t *const UrlConfigLogoPng;
extern const wchar_t *const UrlDoConfigConfirmSaveHtml;
extern const wchar_t *const UrlCounterViewHtml;
extern const wchar_t *const UrlJavascriptErrorHtml;
extern const wchar_t *const UrlAjaxFetchCounter;
extern const wchar_t *const UrlHeadForm;
extern const wchar_t *const UrlIpAddrLookup;
extern const wchar_t *const UrlPostinfo;

typedef void __fastcall (__closure *TSslMultiWebDisplayEvent)(TObject *Sender, const String Msg);

class TSslMultiWebDataModule
{
public:
    String IniFileName;
    String ImagesDir;
    String UploadDir;
    String Port;
    TSslMultiWebDisplayEvent OnDisplay = nullptr;
    TIcsMailQueue *IcsMailQueue = nullptr;
    TIcsGeoTools *IcsGeoTools = nullptr;

    const String &DataDir() const { return FDataDir; }
    const String &CounterFileName() const { return FCounterFileName; }
    void SetDataDir(const String &Value);
    int CounterValue(const String &CounterName, int DefaultValue) const;
    int CounterIncrement(const String &CounterRef) const;
    void LoadConfig();
    void SaveConfig() const;
    void Display(const String &Msg) const;

private:
    String FDataDir;
    String FCounterFileName;
};

extern TSslMultiWebDataModule *SslMultiWebDataModule;

class TAppSrvSessionData : public TWebSessionData
{
    typedef TWebSessionData inherited;
private:
    String FUserCode;
    TDateTime FLogonTime;
    TDateTime FLastRequest;
    int FRequestCount = 0;
    String FIP;
    String FLoginChallenge;
    String FConfigPort;
    String FConfigTempDir;
    bool FConfigHasLogo = false;
    int FTempVar = -1;
public:
    __fastcall virtual TAppSrvSessionData(TComponent *AOwner);
__published:
    __property String UserCode = {read=FUserCode, write=FUserCode};
    __property TDateTime LogonTime = {read=FLogonTime, write=FLogonTime};
    __property int RequestCount = {read=FRequestCount, write=FRequestCount, nodefault};
    __property TDateTime LastRequest = {read=FLastRequest, write=FLastRequest};
    __property String IP = {read=FIP, write=FIP};
    __property String LoginChallenge = {read=FLoginChallenge, write=FLoginChallenge};
    __property String ConfigPort = {read=FConfigPort, write=FConfigPort};
    __property String ConfigTempDir = {read=FConfigTempDir, write=FConfigTempDir};
    __property bool ConfigHasLogo = {read=FConfigHasLogo, write=FConfigHasLogo, nodefault};
    __property int TempVar = {read=FTempVar, write=FTempVar, nodefault};
};

class TUrlHandlerBase : public TUrlHandler
{
    typedef TUrlHandler inherited;
protected:
    bool NotLogged();
    TAppSrvSessionData *SessionData();
    void Relocate(const String &Location);
public:
    __fastcall virtual TUrlHandlerBase(TComponent *AOwner) : TUrlHandler(AOwner) {}
};

class TUrlHandlerMailer : public TUrlHandler
{
    typedef TUrlHandler inherited;
private:
    std::unique_ptr<TWSocket> FWSocket;
    std::unique_ptr<TIcsTimer> FAbortTimer;
    String sMailBody;
    String sMailFrom;
    String sMailName;
    String sMailTo;
    String sIPAddr;
    String sUserIPHost;
    String sPageUrl;
    String errorMsg;
    void __fastcall HandleBackgroundExceptions(TObject *Sender, Exception *E, bool &CanClose);
    void __fastcall DoneDnsLookup(TObject *Sender, System::Word Error);
    void __fastcall TimerAbortTimer(TObject *Sender);
public:
    __fastcall virtual TUrlHandlerMailer(TComponent *AOwner) : TUrlHandler(AOwner) {}
    __fastcall virtual ~TUrlHandlerMailer();
    virtual void __fastcall Execute();
};

class TUrlHandlerLoginFormHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerLoginFormHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerDoLoginSecureHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerDoLoginSecureHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerJavascriptErrorHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerJavascriptErrorHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerDefaultDoc : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerDefaultDoc(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerHomePageHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerHomePageHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerUploadData : public TUrlHandler
{
public:
    __fastcall virtual TUrlHandlerUploadData(TComponent *AOwner) : TUrlHandler(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerUploadFile : public TUrlHandler
{
public:
    __fastcall virtual TUrlHandlerUploadFile(TComponent *AOwner) : TUrlHandler(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerPostInfo : public TUrlHandler
{
public:
    __fastcall virtual TUrlHandlerPostInfo(TComponent *AOwner) : TUrlHandler(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerDemoAuthAll : public TUrlHandler
{
public:
    __fastcall virtual TUrlHandlerDemoAuthAll(TComponent *AOwner) : TUrlHandler(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerHelloWorld : public TUrlHandler
{
public:
    __fastcall virtual TUrlHandlerHelloWorld(TComponent *AOwner) : TUrlHandler(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerHead : public TUrlHandlerBase
{
private:
    String FUrl;
    String FResponse;
    std::unique_ptr<TSslHttpRest> FCli;
    bool FAllHdrs = false;
    String GenerateMath();
    bool VerifyMath(const String &S);
    void AnswerHeadForm(const String &Url, const String &Response);
    void __fastcall HeadRequestDone(TObject *Sender, THttpRequest RqType, System::Word ErrCode);
    void __fastcall HeadRequestTimeout(TObject *Sender, TTimeoutReason Reason);
public:
    __fastcall virtual TUrlHandlerHead(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerCounterViewHtml : public TUrlHandlerBase
{
private:
    std::unique_ptr<TStringList> FCounters{new TStringList()};
    std::unique_ptr<TStringList> FCountersSelected{new TStringList()};
    void __fastcall GetRowData(TObject *Sender, const String TableName, int Row,
                               TStringIndex *TagData, bool &More, TObject *UserData);
public:
    __fastcall virtual TUrlHandlerCounterViewHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerAjaxFetchCounter : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerAjaxFetchCounter(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerCounterJpg : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerCounterJpg(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerConfigFormHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerConfigFormHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerDoConfigHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerDoConfigHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerConfigLogoPng : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerConfigLogoPng(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlHandlerDoConfigConfirmSaveHtml : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlHandlerDoConfigConfirmSaveHtml(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

class TUrlIpAddrLookup : public TUrlHandlerBase
{
public:
    __fastcall virtual TUrlIpAddrLookup(TComponent *AOwner) : TUrlHandlerBase(AOwner) {}
    virtual void __fastcall Execute();
};

void RegisterMultiWebClasses();
void ForceRemoveDir(const String &Dir);
void CleanupTimeStampedDir(const String &Dir);

#endif
