/*---------------------------------------------------------------------------*/
/* url_handler.h                                                             */
/* copyright (c) innovaphone 2021                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#define URLHANDLER_MAX_PAYLOAD_SIZE 16384

typedef std::list<class LocalConnection *> LocalConnections;

class LocalListener : public USocket
{
    class UrlHandler * urlHandler;
    void SocketBindResult(ISocket * const socket, const char * localAddr, word localPort) override;
    void SocketListenResult(ISocket * const socket, const char * remoteAddr, word remotePort) override;
    void SocketShutdown(ISocket * const socket, shutdownreason_t reason) override;
    void SocketRecvCanceled(ISocket * const socket, void * buf) override;
public:
    LocalListener(class UrlHandler * urlHandler) { this->urlHandler = urlHandler; }
};

class UrlHandler : public IShutdownHandler, public IInstanceLog, public IUrlHandler {
    friend class LocalListener;

    IIoMux * iomux;
    class ISocketProvider * localSocketProvider;
    class ILauncherApi * launcherApi;
    class ISignalingApp * signalingApp;
    class ISocket * socket;
    bool stopping;
    LocalListener localListener;
    LocalConnections localConnections;

    void LocalSocketBindResult(ISocket * const socket, const char * localAddr, word localPort);
    void LocalSocketListenResult(ISocket * const socket, const char * remoteAddr, word remotePort);
    void LocalSocketShutdown(ISocket * const socket, shutdownreason_t reason);
    void LocalSocketRecvCanceled(ISocket * const socket, void * buf);

    void HandleUrl(const char * url) override;

    void Shutdown() override;
    void ShutdownTimeout() override;

    void TryStop();

    bool IsE164(const char * num);

public:
    UrlHandler(IIoMux * const iomux, class ISocketProvider * localSocketProvider, const char * urlHandlerLocalAddr);
    virtual ~UrlHandler();

    const char * GetAppName() const { return "UrlHandler"; }
    const char * GetAppDomain() const { return NULL; }
    void SetLauncherApi(class ILauncherApi * launcherApi) { this->launcherApi = launcherApi; };
    void SetSignalingApp(class ISignalingApp* signalingApp) { this->signalingApp = signalingApp; };
    void LocalConnectionClosed(class LocalConnection * connection);
    void Message(char * buffer);
};

class LocalConnection : public USocket
{
    void SocketAcceptComplete(ISocket * const socket) override;
    void SocketShutdown(ISocket * const socket, shutdownreason_t reason) override;
    void SocketRecvResult(ISocket * const socket, void * buf, size_t len) override;
    void SocketRecvCanceled(ISocket * const socket, void * buf) override;

    UrlHandler * instance;
    class ISocket * socket;
    char recvBuf[URLHANDLER_MAX_PAYLOAD_SIZE];
    unsigned recvLen;
    unsigned jsonLevel;
    bool jsonQuotes;
    bool jsonEsc;
    bool closing;

public:
    LocalConnection(UrlHandler * instance);
    virtual ~LocalConnection();

    void Close();
};

