/*---------------------------------------------------------------------------*/
/* client.h                                                                  */
/* copyright (c) innovaphone 2018                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

class UClient
{
public:
    virtual UWebserverGet * ClientWebserverGetAccept(const char * resourceName) { return NULL; };
    virtual void ClientConfigToJson(class json_io & json, word base, char * & tmp) = 0;
    virtual void ClientConfigOptionsToJson(class json_io & json, word base, char * & tmp) = 0;
    virtual void ClientJsonToConfig(class json_io & json, word base, void * context) = 0;
    virtual void ClientGetLogActive(bool active) = 0;
    virtual void ClientFixCert() {};
    virtual bool ClientEMailLogAvailable() { return false; };
    virtual void ClientEMailLog() {};
    virtual void ClientClearLog() {};
    virtual void ClientAutostartSettingsApp(char * name, size_t name_len) {};
    virtual void ClientStartAutostartSettingsApp(const char *name) {};
};

class IClient
{
public:
#define ICLIENT_LOG_FLAG_COUNT 21
    static ulong64 LogFlagTable[ICLIENT_LOG_FLAG_COUNT];
    virtual void WebserverRequestClosed() {};
    virtual void ClientConfigChanged(class UClient * user, void * context) = 0;
};

class Client : public UWebserverPlugin, public IShutdownHandler, public IInstanceLog, public STaskContext, public IClient
{
    class IIoMux * iomux;
    istd::list<class AppClientSession> sessions;

    void WebserverPluginClose(IWebserverPlugin * plugin, wsp_close_reason_t reason, bool lastUser);
    void WebserverPluginHttpListenResult(IWebserverPlugin * plugin, ws_request_type_t requestType, char * resourceName, const char * registeredPathForRequest, ulong64 dataSize);
    void WebserverPluginWebsocketListenResult(IWebserverPlugin * plugin, const char * path, const char * registeredPathForRequest, const char * host);
    void WebserverRequestClosed();
    void ClientConfigChanged(class UClient * user, void * context);

    const char * GetAppName() const { return "client"; }
    const char * GetAppDomain() const { return ""; }

    void Shutdown();
    void ShutdownTimeout();
    void Stop();

public:
    Client(IIoMux * const iomux, IWebserverPluginProvider * webserverPluginProvider, ISocketProvider * localSocketProvider, const char * webserver, const char * webserverPath,
        class UDebugReadLog * debugReadLogUser, class UClient * clientUser, const char * password);
    ~Client();
    void TryStop();

    int pendingWebRequests;
    int pendingGetLogs;
    bool stopping;
    class IWebserverPlugin * webserverPlugin;
    class UDebugReadLog * debugReadLogUser;
    class UClient * clientUser;
    char * password;
};

class AppClientSession: public AppWebsocket, public istd::listElement<AppClientSession> {
    char * AppWebsocketPassword() override;
    void AppWebsocketMessage(class json_io & msg, word base, const char * mt, const char * src) override;
    bool AppWebsocketConnectComplete(class json_io & msg, word info) override;
    void AppWebsocketSendResult() override;
    void AppWebsocketClosed() override;

    class IInstanceLog * log;
    class IIoMux * iomux;

    bool closed;

public:
    AppClientSession(class Client * client, IIoMux * const iomux);
    ~AppClientSession();

    const char * getSip() { return sip; };

    class Client * client;
};

class AppClientSrc {
public:
    AppClientSrc(class AppClientSession * session, const char * src);
    ~AppClientSrc();

    class AppClientSession * session;
    char * src;
};

class TaskGetLog : public UWebserverGet, public UTask {
    void WebserverGetRequestAcceptComplete(IWebserverGet * const webserverGet) override;
    void WebserverGetSendResult(IWebserverGet * const webserverGet) override;
    void WebserverGetCloseComplete(IWebserverGet * const webserverGet) override;

    void TaskComplete(class ITask * const task);
    void TaskFailed(class ITask * const task);
    void TaskProgress(class ITask * const task, dword progress);

    class Client * client;
    class IWebserverGet * get;
    class IDebugReadLog * readLog;
    bool reading;
    char * filename;

public:
    TaskGetLog(class Client * client, const char * filename);
    ~TaskGetLog();
};
