/*---------------------------------------------------------------------------*/
/* appclient_ringer.h                                                        */
/* copyright (c) innovaphone 2017                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

typedef struct {
    int id;
    const char *name;
} RingerIdNameItem;

class AppClientRinger: public UWebserverPlugin, public IShutdownHandler, public IInstanceLog, public IAppClientRinger, public URingerIo, public UDeviceIo, public URingtone, public URemoteServices
{
    IIoMux * iomux;
    class IRinger * ringer;
    class IRingerIo * ringerIo;
    class IRingerIo * remoteRingerIo;
    char *appName;
    char *appDomain;
    istd::list<class AppClientRingerSession> sessions;

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

    void CloseRingerIoComplete();

    bool ringerIoInitialized;

    void QueryDevices(bool cleanDevices) override;

    // overrides of IInstanceLogs
    const char * GetAppName() const { return appName; }
    const char * GetAppDomain() const { return appDomain; }

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

    void MediaIoDeviceAdded(IDeviceIo * deviceIo, void * context, const char *deviceId, int deviceType, unsigned deviceCapabilities, const char *deviceName, bool selected) override;
    void MediaIoDeviceFailed(IDeviceIo* deviceIo, void* context, const char* deviceId) override;
    void MediaIoDeviceRemoved(IDeviceIo * deviceIo, void * context, const char *deviceId) override;
    void MediaIoQueryDevicesResult(IDeviceIo * deviceIo, void * context) override;

    void RingerIoRingtoneAdded(IRingerIo * ringerIo, void * context, const char *ident, const char *title, bool selected) override;
    void RingerIoRingtoneRemoved(IRingerIo * ringerIo, void * context, const char *ident, const char *title) override;
    void RingerIoQueryRingtonesResult(IRingerIo * ringerIo, void * context) override;

    void RingerIoNotificationToneAdded(IRingerIo * ringerIo, void * context, const char *ident, const char *title, bool selected) override;
    void RingerIoNotificationToneRemoved(IRingerIo * ringerIo, void * context, const char *ident, const char *title) override;
    void RingerIoQueryNotificationTonesResult(IRingerIo * ringerIo, void * context) override;

    // URemoteServices 
    void ClientConnected() override { this->myAppsPlugingConnected = true; }
    void ClientDisconnected() override { 
        this->myAppsPlugingConnected = false; 
        if (this->ringerIo) this->ringerIo->QueryDevices(NULL);
    }
    void ServerConnected() override {};
    void ServerDisconnected() override {};
    void Message(const char* type, class json_io& msg, word base) override {};
public:
    AppClientRinger(IIoMux * const iomux, IWebserverPluginProvider * webserverPluginProvider, ISocketProvider * localSocketProvider, AppInstanceArgs * args, class MediaConfiguration* mediaConfiguration);
    ~AppClientRinger();

    static const char *IdName(RingerIdNameItem *map, int id);
    static int NameId(RingerIdNameItem *map, const char *name);

    void RemoveSession(class AppClientRingerSession * session);
    class IRingerIo * GetRingerIo() { return this->ringerIo; };

    void SetRemoteRingerIo(class IRingerIo* remoteRinger) { this->remoteRingerIo = remoteRinger; };
    class IRingerIo * GetRemoteRingerIo() { return this->remoteRingerIo; };

    bool myAppsPlugingConnected;
    class MediaConfiguration* mediaConfiguration;
    bool stopping;
    bool stoppingRinger;
    char * pwd;
    IWebserverPlugin * webserverPlugin;
};

class AppClientRingerSession: public AppWebsocket, public istd::listElement<AppClientRingerSession> {
    void AppWebsocketAccept(class UWebsocket * uwebsocket) { appclient->webserverPlugin->WebsocketAccept(uwebsocket); };
    char * AppWebsocketPassword() { return appclient->pwd; };
    void AppWebsocketMessage(class json_io & msg, word base, const char * mt, const char * src);
    bool AppWebsocketConnectComplete(class json_io & msg, word info);
    void AppWebsocketSendResult();
    void AppWebsocketClosed();

    class IInstanceLog * log;
    class IIoMux * iomux;

    bool closed;

    class AppClientRingerSrc * ringerDevicesSessionContext;
    class AppClientRingerSrc * ringerRingtonesSessionContext;
    class AppClientRingerSrc * ringerNotificationsTonesSessionContext;
public:
    AppClientRingerSession(class AppClientRinger * appclient, IIoMux * const iomux, class IRingerIo * ringerIo, class IDeviceIo * deviceIo);
    ~AppClientRingerSession();

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

    class IDeviceIo * deviceIo;
    class IRingerIo * ringerIo;
    class AppClientRinger * appclient;
};

class AppClientRingerSrc: public MediaProviderContext {
public:
    AppClientRingerSrc(class AppClientRingerSession * session, const char * src, const char * app);
    ~AppClientRingerSrc();
};
