/*++

Program name:

  dm

Module Name:

  WebSocketModule.hpp

Notices:

  Module: WebSocket

Author:

  Copyright (c) Prepodobny Alen

  mailto: alienufo@inbox.ru
  mailto: ufocomp@gmail.com

--*/

#ifndef DM_WEB_SOCKET_MODULE_HPP
#define DM_WEB_SOCKET_MODULE_HPP
//----------------------------------------------------------------------------------------------------------------------

#include "Common.hpp"
//----------------------------------------------------------------------------------------------------------------------

extern "C++" {

namespace Apostol {

    namespace Module {

        class CClientContext: public CContext {
        private:

            CWebSocketClientManager m_ClientManager {};

        public:

            CClientContext() = default;

            CClientContext(const CClientContext &Context): CContext(Context) {
                Assign(Context);
            }

            explicit CClientContext(const CString &Name, const CLocation &URI): CContext(Name, URI) {

            }

            CWebSocketClientManager& ClientManager() { return m_ClientManager; }

            const CWebSocketClientManager& ClientManager() const { return m_ClientManager; }

        };
        //--------------------------------------------------------------------------------------------------------------

        typedef TPair<CClientContext> CClientContextPair;
        typedef TPairs<CClientContext> CClientContextList;

        //--------------------------------------------------------------------------------------------------------------

        //-- CWebSocketModule ------------------------------------------------------------------------------------------

        //--------------------------------------------------------------------------------------------------------------

        class CWebSocketModule: public CCustomModule {
        private:

            CClientContextPair m_DefaultServer { BPS_BM_SERVER_ADDRESS, CClientContext(BPS_BM_SERVER_ADDRESS, CLocation(BPS_SERVER_URL)) };

            CClientContextList m_Servers {};

            void InitServerList();

            CWebSocketClient *GetWebSocketClient(CClientContext &Context);
            void CreateWebSocketClient(CClientContext &Context);

            static CWebSocketClient *GetConnectedClient(const CClientContext &Context);

            int CurrentContextIndex(const CString &Params);
            CWebSocketClient *GetConnectedClient(const CString &Params);

        protected:

            void DoAccount(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI) override;
            void DoDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action) override;
            void DoProxy(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI) override;
            void DoSignature(CHTTPServerConnection *AConnection) override;

            void DoWebSocketError(CTCPConnection *AConnection);
            void DoClientConnected(CObject *Sender);
            void DoClientDisconnected(CObject *Sender);

            void DoClientHeartbeat(CObject *Sender);
            void DoClientTimeOut(CObject *Sender);

            void DoClientMessage(CObject *Sender, const CWSMessage &Message);
            void DoClientError(CObject *Sender, int Code, const CString &Message);

            void DoAuthorizeEvent(CObject *Sender, const CWSMessage &Request, const CWSMessage &Response);
            void DoSubscribeEvent(CObject *Sender, const CWSMessage &Request, const CWSMessage &Response);
            void DoKeyEvent(CObject *Sender, const CWSMessage &Request, const CWSMessage &Response);

            void DoWebSocketClientEvent(CObject *Sender, const CWSMessage &Request, const CWSMessage &Response);

        public:

            explicit CWebSocketModule(CModuleProcess *AProcess, const CString &ModuleName, const CString &SectionName);

            ~CWebSocketModule() override = default;

            static class CWebSocketModule *CreateModule(CModuleProcess *AProcess) {
                return new CWebSocketModule(AProcess, "web socket", "module/WebSocket");
            }

            void Heartbeat(CDateTime Now) override;

            void Reload() override;

        };
    }
}

using namespace Apostol::Module;
}
#endif //DM_WEB_SOCKET_MODULE_HPP
