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

class AppWebsocketClientProvider : public IAppWebsocketClientProvider {
    IAppWebsocketClient * Create(class UAppWebsocketClient * const user, class IInstanceLog * const log) override;
    class IIoMux * iomux;
    class ISocketProvider * tcpSocketProvider;
    class ISocketProvider * tlsSocketProvider;
    class IDns * dns;
public:
    AppWebsocketClientProvider(class IIoMux * const iomux,
                               class ISocketProvider * const tcpSocketProvider,
                               class ISocketProvider * const tlsSocketProvider,
                               class IDns * const dns);

};

class AppWebsocketClient : public IAppWebsocketClient, public UWebsocketClient, public UAppWebsocketAuthenticator, public UTimer, public UIoExec {
    class IIoMux * const iomux;
    class ISocketProvider * const tcpSocketProvider;
    class ISocketProvider * const tlsSocketProvider;
    class IDns * const dns;
    class UAppWebsocketClient * user;
    class IInstanceLog * log;
    class IAppWebsocketAuthenticator * authenticator;
    class ITimer reconnectTimer;
    bool connected;
    bool autoReconnect;
    bool waitLoginResult;
    char * fragmented;
    unsigned fragmentedLen;
    unsigned reconnectTimeout;
    char * app;
    char * domain;
    char * sip;
    char * guid;
    char * dn;
    char * password;
    char * websocketUri;
    char * usr;
    char * appObj;
    char * info;
    char key[65];
    
    void CreateClient();
    void StartReconnectTimer();
    void TimerOnTimeout(ITimer * timer) override;
    void IoExec(void * execContext) override;

    void AppWebsocketAuthenticatorClosed(class IAppWebsocketAuthenticator * authenticator) override;
    void AppWebsocketAuthenticatorGetLoginResult(class IAppWebsocketAuthenticator * authenticator, const char * domain, const char * sip, const char * guid, const char * dn, const char * pbxObj, const char * app, const char * info, const char * digest, const char * key) override;
    void AppWebsocketAuthenticatorGetLoginError(class IAppWebsocketAuthenticator * authenticator) override;

    void CalculateKey(const char * challenge);
    bool RecvAppChallengeResult(class json_io & json, word base);
    bool RecvAppLoginResult(class json_io & json, word base);

protected:
    class IWebsocketClient * client;

    virtual void WebsocketConnectComplete(IWebsocketClient * const websocket) override;
    void WebsocketCloseComplete(IWebsocketClient * const websocket, closereason_t reason) override;
    void WebsocketSendResult(IWebsocketClient * const websocket) override;
    void WebsocketRecvResult(IWebsocketClient * const websocket, void * buf, size_t len, bool text, bool isFragment) override;
    void * WebsocketRecvBuffer(size_t len) override;
    void WebsocketRecvCanceled(IWebsocketClient * const websocket, void * buf) override;

public:
    AppWebsocketClient(class IIoMux * const iomux, class UAppWebsocketClient * user, class ISocketProvider * const tcpSocketProvider, class ISocketProvider * const tlsSocketProvider, class IDns * const dns, class IInstanceLog * log);
    virtual ~AppWebsocketClient();

    void Connect(const char * websocketUri, const char * password, const char * app, const char * domain, const char * sip, const char * guid, const char * dn, bool autoReconnect = false, const char * usr = NULL, const char * appObj = NULL, const char * info = NULL) override;
    void Connect(const char * websocketUri, const char * app, class IAppWebsocketAuthenticator * authenticator, bool autoReconnect = false) override;
    void MessageComplete() override;
    void MessageSend(class json_io & msg, char * buffer) override;
    void MessageSendText(const char * buffer) override;
    void MessageSendBinary(byte * buffer, size_t len) override;
    void Encrypt(const char * seed, const char * data, char * out, size_t outLen) override;
    void Decrypt(const char * seed, const char * data, char * out, size_t outLen) override;
    void Hash(const char * seed, const char * data, char * out, size_t outLen) override;
    void Close() override;
};
