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

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

class KnownConsumerItem : public istd::listElement<KnownConsumerItem> {
public:
    KnownConsumerItem(const char * client, const char * consumer) {
        this->client = _strdup(client);
        this->consumer = _strdup(consumer);
        this->disablePowerSaving = false;
    }
    ~KnownConsumerItem() {
        if(this->client) free(this->client);
        if(this->consumer) free(this->consumer);
    }
    char * client;
    char * consumer;
    bool disablePowerSaving;
};

class UuidConsumerItem : public istd::listElement<UuidConsumerItem> {
public:
    UuidConsumerItem(const char * uuid, const char * client, const char * consumer) {
        this->uuid = _strdup(uuid);
        this->client = _strdup(client);
        this->consumer = _strdup(consumer);
    }
    ~UuidConsumerItem() {
        if(this->uuid) free(this->uuid);
        if(this->client) free(this->client);
        if(this->consumer) free(this->consumer);
    }
    char * uuid;
    char * client;
    char * consumer;
};

class LauncherApiHandlerService : public AppService {
    void AppServiceApps(istd::list<AppServiceApp> * appList) override {};

public:
    LauncherApiHandlerService(class IIoMux * const iomux, IWebserverPluginProvider * const webserverPluginProvider, class ISocketProvider * localSocketProvider, class ISocketProvider * tcp, class ISocketProvider * tls, class IDns * dns, AppServiceArgs * args, const char * url, const char * pwd, const char * dn, const char * localSocketPath = NULL);
    ~LauncherApiHandlerService();

    class AppInstance * CreateInstance(AppInstanceArgs * args) override;

    class IIoMux * iomux;
    class IWebserverPluginProvider * webserverPluginProvider;
    class ISocketProvider * localSocketProvider;
    class ISocketProvider * tcp;
    class ISocketProvider * tls;
    class IDns * dns;
    class IUrlHandler * urlHandler;
    char * url;
    char * pwd;
    char * dn;
    char * localSocketPath;
    class LauncherApiHandler * launcherApi;
};

typedef std::list<class WebsocketConnection *> WebsocketConnections;
typedef std::list<class ULauncherApi *> LauncherApiUsers;

class LauncherApiHandler : public AppInstance, public ApiWebsocketClient, public UWebserverPlugin, public ILauncherApi
{
    void Stop() override;
    void AppInstanceShutdownTimeout() override;
    void TryStop();

    bool stopping;
    bool closed;
    class IWebserverPlugin * webserverPlugin;
    WebsocketConnections websocketConnections;
    class LocalConnectionTest * localConnectionTest;
    class PhoneApiConsumer * phone;
    class ChatApiConsumer * chat;
    class EventsApiConsumer * events;
    class ClientApiConsumer * clientApi;
    class CacheableApiConsumer * cacheableApi;
    class LauncherUserApiConsumer * launcherUser;
    class LauncherApiProvider * launcher;

    void ApiWebsocketClientCloseComplete() override;
    void WebserverPluginWebsocketListenResult(IWebserverPlugin * plugin, const char * path, const char * registeredPathForRequest, const char * host) override;
    void WebserverPluginClose(IWebserverPlugin * plugin, wsp_close_reason_t reason, bool lastUser) override;

public:
    void AddLauncherApiUser(class ULauncherApi * launcherApiUser) override;
    void RemoveLauncherApiUser(class ULauncherApi * launcherApiUser) override;
    void StartCall(const char * sip, const char * num, const char * name, StartCallVideoMode videoMode) override;
    void PrepareCall(const char * text) override;
    void StartChat(const char * sip) override;
    void SendEvent(dword code, int severtiy, ulong64 time, const char* text, const char* details, const char* src) override;
    void SetPushToken(const char * pushToken) override;
    void SetClose(bool closeSupported) override;
    void SetDocking(bool dockingSupported, bool docked) override;
    void SetAutoOffline(bool offlineSupported, bool offline) override;
    void SetAutostart(bool autostartSupported, bool autostart) override;
    void SetHotkeyAction(bool hotkeySupported, int action, const char * dialNumber) override;
    void SetGsmState(bool gsmSupported, enum GsmCallState gsmCallState) override;
    void SetDetach(bool detach) override;
    void SetConfigApp(const char* url) override;
    void SetStatusHeader(const char * url) override;
    void SetRingerServiceUrl(const char * url) override;
    void SetAudioServiceUrl(const char * url) override;
    void SetVideoServiceUrl(const char * url) override;
    void SetAppSharingServiceUrl(const char * url) override;
    void SetSignalingServiceUrl(const char* url) override;
    void SetRemoteControlServiceUrl(const char* url) override;
    void SetServicePassword(const char * url) override;
    void SetExpectTouches(bool expectTouchesSupported, bool expectTouches) override;
    void SetShownLocked(bool shownLockedSupported, bool shownLocked) override;
    void SetProximity(bool proximitySupported, bool proximity) override;
    void SetNoPushAutostart(bool noPushAutostartSupported) override;
    void SetRunningClientServer(bool runningClientServer) override;
    void SetBusylightHttpPort(int port) override;
    void SetLock(bool lockSupported) override;
    void SetLockPinNumberCount(int signCount) override;
    void SetLockClock(char * clock) override;
    void SetLockTimeout(int timeout) override;
    void SetLockEmergencyNumbers(char * emergency) override;
    void LauncherApiLocalNotificationClicked(const char * ref, LocalNotificationAction action, const char * replyText = nullptr) override;
    void WakePhone();
    void GoHome();
    void Lock();
    void OpenPermalink(const char * link);
    void SendCheckPinResult(const char * client, const char * consumer, const char * src, bool ok) override;

    LauncherApiHandler(LauncherApiHandlerService * service, AppInstanceArgs * args);
    ~LauncherApiHandler();

    void WebsocketConnectionClosed(class WebsocketConnection * connection);
    void LocalConnectionTestClosed();
    void Message(char * buffer);

    static const char *IdName(LauncherApiIdNameItem *map, int id);
    static int NameId(LauncherApiIdNameItem *map, const char *name);
    static int NotificationNameId(NotificationIdNameItem* map, const char* name);

    class LauncherApiHandlerService * service;
    LauncherApiUsers launcherApiUsers;
};

class WebsocketConnection : public UWebsocket
{
    void WebsocketAcceptComplete(class IWebsocket * websocket) override;
    void WebsocketSendResult(class IWebsocket * websocket) override;
    void WebsocketRecvResult(class IWebsocket * websocket, void * buffer, size_t len, bool text, bool isFragmented) override;
    void * WebsocketRecvBuffer(size_t len) override;
    void WebsocketRecvCanceled(class IWebsocket * websocket, void * buffer) override;
    void WebsocketCloseComplete(class IWebsocket * websocket, ws_close_reason_t reason) override;

    class LauncherApiHandler * instance;
    class IWebsocket * websocket;
    bool closing;

public:
    WebsocketConnection(LauncherApiHandler * instance, IWebserverPlugin * plugin);
    virtual ~WebsocketConnection();

    void Close();
};

class PhoneApiConsumer : public ApiConsumer
{
public:
    PhoneApiConsumer(LauncherApiHandler * client);
    ~PhoneApiConsumer();

    void StartCall(const char * sip, const char * num, bool adjust = true, const char *dn = NULL, StartCallVideoMode videoMode = START_CALL_VIDEO_MODE_DEFAULT);
    void PrepareCall(const char * text, bool adjust = true);
    void ConnectCall(void);
    void DisconnectCall(void);
};

class ChatApiConsumer : public ApiConsumer
{
public:
    ChatApiConsumer(LauncherApiHandler * client);
    ~ChatApiConsumer();

    void StartChat(const char * sip);
};

class ClientApiConsumer : public ApiConsumer
{
    LauncherApiHandler * client;
public:
    ClientApiConsumer(LauncherApiHandler * client);
    ~ClientApiConsumer();

    void ApiConsumerUpdate(class json_io & model, word base);
    void WakePhone();
    void GoHome();
    void Lock();
    void OpenPermalink(const char * link);
};

class EventsApiConsumer : public ApiConsumer
{
public:
    EventsApiConsumer(LauncherApiHandler* client);
    ~EventsApiConsumer();

    void SendEvent(dword code, int severtiy, ulong64 time, const char * text, const char * details, const char * src);
};

class CacheableApiConsumer : public ApiConsumer
{
    LauncherApiHandler * client;
public:
    CacheableApiConsumer(LauncherApiHandler * client);
    ~CacheableApiConsumer();

    void ApiConsumerUpdate(class json_io & model, word base);
};

class LauncherUserApiConsumer : public ApiConsumer
{
    bool ExtractRef(char * ref_buffer, const char ** consumer, const char ** src);
public:
    LauncherUserApiConsumer(LauncherApiHandler * client);
    ~LauncherUserApiConsumer();

    void LocalNotificationClicked(const char * ref, LocalNotificationAction action, const char * replyText = nullptr);
};

class LauncherApiProvider : public ApiProvider
{
    void ApiProviderRecv(const char * client, const char * consumer, const char * src, class json_io & msg, word base) override;
    void ApiProviderConsumerClosed(const char * client, const char * consumer) override;
    void Update();
    int CreateRef(char * ref, const char * consumer, const char * src);

    LauncherApiHandler * client;
    char * pushToken;
    bool closeSupported;
    bool dockingSupported;
    bool docked;
    bool gsmSupported;
    enum GsmCallState gsmCallState;
    bool detach;
    char * configApp;
    char * statusHeader;
    char * ringerService;
    char * audioService;
    char * videoService;
    char * appSharingService;
    char * signalingService;
    char * remoteControlService;
    char * servicePassword;
    bool offline;
    bool offlineSupported;
    bool autostartSupported;
    bool autostart;
    bool expectTouchesSupported;
    bool expectTouches;
    bool shownLockedSupported;
    bool shownLocked;
    bool proximitySupported;
    bool proximity;
    bool noPushAutostartSupported;
    bool cxSupported;
    bool lockSupported;
    int lockPinNumberCount;
    char * lockClock;
    int lockTimeout;
    char * lockEmergencyNumbers;
    bool runningClientServer;
    int busylightHttpPort;
    istd::list<class KnownConsumerItem> knownConsumers;

public:
    LauncherApiProvider(LauncherApiHandler * client);
    ~LauncherApiProvider();

    void SetPushToken(const char * pushToken);
    void SetClose(bool closeSupported);
    void SetDocking(bool dockingSupported, bool docked);
    void SetAutoOffline(bool offlineSupported, bool offline);
    void SetAutostart(bool autostartSupported, bool autostart);
    void SetGsmState(bool gsmSupported, enum GsmCallState gsmCallState);
    void SetDetach(bool detach);
    void SetConfigApp(const char* url);
    void SetStatusHeader(const char * url);
    void SetRingerServiceUrl(const char * url);
    void SetAudioServiceUrl(const char * url);
    void SetVideoServiceUrl(const char * url);
    void SetAppSharingServiceUrl(const char * url);
    void SetSignalingServiceUrl(const char* url);
    void SetRemoteControlServiceUrl(const char* url);
    void SetServicePassword(const char * url);
    void SetExpectTouches(bool expectTouchesSupported, bool expectTouches);
    void SetShownLocked(bool shownLockedSupported, bool shownLocked);
    void SetProximity(bool proximitySupported, bool proximity);
    void SetNoPushAutostart(bool noPushAutostartSupported);
    void CxSupported(bool supported);
    void LockSupported(bool supported);
    void SetLockPinNumberCount(int signCount);
    void SetLockClock(char * clock);
    void SetLockTimeout(int timeout);
    void SetLockEmergencyNumbers(char * emergency);
    void SetRunningClientServer(bool runningClientServer);
    void SetBusylightHttpPort(int port);
    void SendCheckPinResult(const char * client, const char * consumer, const char * src, bool ok);
};
