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

class ISysClientDevicesInstancePath {
public:
    static class ISysClientDevicesInstancePath * Create(const char * name, const char * path, bool online);
    virtual ~ISysClientDevicesInstancePath() {}
    virtual const char * GetName() = 0;
    virtual const char * GetPath() = 0;
    virtual bool GetOnline() = 0;
};

typedef std::list<class ISysClientDevicesInstancePath *> ISysClientDevicesInstancePaths;

typedef enum {
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK,
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED,
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE,
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION,
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST,
    SYSCLIENT_SOFTWARE_UPDATE_RESULT_UKNOWN
} sysclient_software_update_result_t;

#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK_STR                     "ok"
#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED_STR   "downloadFailed"
#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE_STR           "incompatible"
#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION_STR           "installationFailed"
#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST_STR        "connectionLost"
#define SYSCLIENT_SOFTWARE_UPDATE_RESULT_UNKNOWN_STR                "unknown"

inline const char * SysclientSoftwareUpdateResultToChar(sysclient_software_update_result_t result) {
    switch (result)
    {
    case SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK_STR;
    case SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED_STR;
    case SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE_STR;
    case SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION_STR;
    case SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST_STR;
    default: return SYSCLIENT_SOFTWARE_UPDATE_RESULT_UNKNOWN_STR;
    }    
}

inline sysclient_software_update_result_t SysclientSoftwareUpdateResultToEnum(const char * result) {
    sysclient_software_update_result_t r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_UKNOWN;
    if (result) {
        if (strcmp(result, SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK_STR) == 0) r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_OK;
        else if (strcmp(result, SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED_STR) == 0) r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_HTTP_DOWNLOAD_FAILED;
        else if (strcmp(result, SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE_STR) == 0) r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_INCOMPATIBLE;
        else if (strcmp(result, SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION_STR) == 0) r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_INSTALLATION;
        else if (strcmp(result, SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST_STR) == 0) r = SYSCLIENT_SOFTWARE_UPDATE_RESULT_CONNECTION_LOST;
    }
    return r;
}

class ISysClient {
public:
    static class ISysClient * Create(class IIoMux * const iomux, class ISocketProvider * tcpSocketProvider, class ISocketProvider * tlsSocketProvider, class USysClient * uSysclient, 
        const char * serverURI, class IInstanceLog * const log, const char * webserverPassword, 
        const char * macAddress, const char * product, const char * version, const char * platformJson, const char * ethIfsJson = nullptr, const char * major = nullptr, bool isInnovaphoneDevice = false, const char * webserverRootPage = nullptr,
        const char * firmwareVersion = nullptr, const char * bootcodeVersion = nullptr, const char * firmwareFileName = nullptr, const char * bootcodeFileName = nullptr, word webserverPort = 80);
    virtual ~ISysClient() {};
    virtual void SendIdentify(const char * provisioningCode) = 0;
    virtual void SendCustomIdentify(const void * buff, size_t len) = 0;
    virtual void SetAdminPassword(const char * password) = 0;
    virtual void SetEthIfsJson(const char * ethIfsJson) = 0;
    virtual void Close() = 0;
    virtual void Encrypt(const char * seed, const char * data, char * out, size_t outLen) = 0;
    virtual void Decrypt(const char * seed, const char * data, char * out, size_t outLen) = 0;
    virtual void SendDevicesInstancePaths(const char * appServiceId, ISysClientDevicesInstancePaths * paths, const char * devicesType = nullptr) = 0;
    virtual void SoftwareUpdateResult(sysclient_software_update_result_t result) = 0;
};

class USysClient {
public:
    virtual ~USysClient() {};
    virtual void SysClientConnected(class ISysClient * sysClient) = 0;
    virtual void SysClientAuthenticated(class ISysClient * sysClient) {};
    virtual void SysClientSetProvisioningCode(class ISysClient * sysClient, const char * provisioningCode) = 0;
    virtual void SysClientSetSysClientPassword(class ISysClient * sysClient, const char * password) = 0;
    virtual void SysClientSetAdminPassword(class ISysClient * sysClient, const char * password) = 0;
    virtual void SysClientSetConfig(class ISysClient * sysClient, char * buffer) = 0;
    virtual const char * SysClientGetPassword(class ISysClient * sysClient) = 0;
    virtual void SysClientSoftwareUpdate(const char * firmwareVersion, const char * firmwareUrl, const char * bootcodeVersion, const char * bootcodeUrl) {};
    virtual void SysClientClosed(class ISysClient * sysClient) = 0;
};
