#pragma once
#include "ProtocolBase.h"

#if !USER_REAL_PLATFORM
class PlatformReqServerCfgParms {
public:
    std::string vmIp;
    AIGC_JSON_HELPER(vmIp)
};

class PlatformReqClientCfgParms {
public:
    std::string userName;
    std::string token;
    AIGC_JSON_HELPER(userName)
};

class PlatformRspUserSvrCfgParams {
public:
    PlatformRspUserSvrCfgParams() {
        this->svrHost   = TEXT("");
        this->svrPort   = 0;
        this->svrPriKey = TEXT("");
    }

    int         svrPort;
    std::string svrPriKey;
    std::string svrHost;

    AIGC_JSON_HELPER(svrPort, svrPriKey, svrHost)
};

class VitrualMathineInfo {
public:
    VitrualMathineInfo() {
        this->vmId      = 0;
        this->scgPort   = 0;
        this->vmName    = TEXT("");
        this->scgIp     = TEXT("");
        this->vmNetwork = TEXT("");
        this->svrPubKey = TEXT("");
    }

    int         vmId;
    std::string vmName;
    std::string svrPubKey;
    std::string vmNetwork;
    std::string scgIp;
    int         scgPort;

    AIGC_JSON_HELPER(vmId, vmName, svrPubKey, vmNetwork, scgIp, scgPort)
};

class PlatformRspUserClientCfgParams {
public:
    PlatformRspUserClientCfgParams() {
        this->scgTunnelAppId = WG_TUNNEL_SCG_ID;
        this->scgCtrlAppId   = WG_CTRL_SCG_ID;
        this->cliHost        = TEXT("");
    }

    int                           scgCtrlAppId;
    int                           scgTunnelAppId;
    std::string                   cliPriKey;
    std::string                   cliPubKey;
    std::string                   cliHost;
    std::list<VitrualMathineInfo> vmInfoList;

    AIGC_JSON_HELPER(scgCtrlAppId, scgTunnelAppId, cliPriKey, cliPubKey, vmInfoList, cliHost)
};

class PlatformRspServerCfgParams {
public:
    std::string                 code;
    std::string                 message;
    PlatformRspUserSvrCfgParams data;

    AIGC_JSON_HELPER(code, data)
};

class PlatformRspClientCfgParams {
public:
    std::string                    code;
    std::string                    message;
    PlatformRspUserClientCfgParams data;

    AIGC_JSON_HELPER(code, data)
};

#endif

class ReqClientCfgParams {
public:
    std::string identifier;

    AIGC_JSON_HELPER(identifier)
};

class ReqHeartParams {
public:
    std::string message;

    AIGC_JSON_HELPER(message)
    AIGC_JSON_HELPER_DEFAULT(message = TEXT("PING"))
};

class RspHeartParams : public ResponseStatus {
public:
    std::string message;

    AIGC_JSON_HELPER(message)
    AIGC_JSON_HELPER_BASE((ResponseStatus *)this)
    AIGC_JSON_HELPER_DEFAULT(message = TEXT("PONG"))
};

class ReqGetUserCfgParams {
public:
    std::string user;
    std::string token;

    AIGC_JSON_HELPER(user, token)
};

class RspUserSevrCfgParams {
public:
    RspUserSevrCfgParams() {
        this->svrAddress    = TEXT("");
        this->svrListenPort = 0;
        this->svrPrivateKey = TEXT("");
    }

    int         svrListenPort;
    std::string svrPrivateKey;
    std::string svrAddress;

    AIGC_JSON_HELPER(svrListenPort, svrPrivateKey, svrAddress)
};

class ReqStartTunnelParams {
public:
    bool isStart;
    AIGC_JSON_HELPER(isStart)
};

class ReqUserSetCliCfgParams {
public:
    std::string cliPublicKey;
    std::string cliNetwork;
    std::string cliTunnelAddr;

    AIGC_JSON_HELPER(cliPublicKey, cliNetwork, cliTunnelAddr)
};

class RspUserSetCliCfgParams : public ResponseStatus {
public:
    std::string svrNetwork;

    AIGC_JSON_HELPER(svrNetwork)
    AIGC_JSON_HELPER_BASE((ResponseStatus *)this)
};

class VitrualMathineCfg {
public:
    VitrualMathineCfg() {
        this->vmId         = 0;
        this->vmName       = TEXT("");
        this->scgGateway   = TEXT("");
        this->vmNetwork    = TEXT("");
        this->svrPublicKey = TEXT("");
    }

    int         vmId;
    std::string vmName;
    std::string svrPublicKey;
    std::string vmNetwork;
    std::string scgGateway;

    AIGC_JSON_HELPER(vmId, vmName, svrPublicKey, vmNetwork, scgGateway)
};

class RspUsrCliConfigParams {
public:
    int                          scgCtrlAppId;
    int                          scgTunnelAppId;
    std::string                  cliPrivateKey;
    std::string                  cliPublicKey;
    std::string                  cliAddress;
    std::list<VitrualMathineCfg> vmConfig;

    AIGC_JSON_HELPER(scgCtrlAppId, scgTunnelAppId, cliPrivateKey, cliPublicKey, cliAddress, vmConfig)
};

#if USER_REAL_PLATFORM
#define GET_CLIENTCFG_PATH TEXT("/tunnel/getuserconfig")
#define GET_SERVERCFG_PATH TEXT("/tunnel/getserverconfig")
#else
#define GET_CLIENTCFG_PATH TEXT("/sc/open-portal/openapi/scc/cliTunnelCfg")
#define GET_SERVERCFG_PATH TEXT("/sc/open-portal/openapi/scc/svrTunnelCfg")
#endif

#define SET_CLIENTCFG_PATH     TEXT("/tunnel/setconfig")
#define SET_CLIENTSTART_TUNNEL TEXT("/tunnel/start")
#define SET_CLIENTHEART_PATH   TEXT("/tunnel/heart")

int InitControlServer(const TCHAR *pUserSvrUrl);

/**
 * @brief  调用 RESTful POST 接口并获取服务端返回数据
 * @param[in] pUrlPath 服务端 URL 路径
 * @param[in] pReq 请求消息
 * @param[in] pRsp 返回消息
 * @param[in] platformServer 访问平台还是访问控制服务
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_SYSTEM_UNINITIALIZE 服务端URL未初始化
 * - -ERR_JSON_CREATE 创建 JSON 字符串失败
 * - -ERR_HTTP_POST_DATA 调用 POST 方法失败
 * - -ERR_HTTP_SERVER_RSP 服务端返回失败（非200）
 * - -ERR_READ_FILE 服务端返回空数据
 * - -ERR_JSON_DECODE 解析 JSON 数据失败
 * - ERR_SUCCESS 成功
 */
template<class T1, class T2>
int ProtolPostMessage(const TCHAR          *pUrlPath,
                      ProtocolRequest<T1>  *pReq,
                      ProtocolResponse<T2> *pRsp,
                      bool                  platformServer);

extern template int ProtolPostMessage(const TCHAR                            *pUrlPath,
                                      ProtocolRequest<ReqGetUserCfgParams>   *pReq,
                                      ProtocolResponse<RspUserSevrCfgParams> *pRsp,
                                      bool                                    platformServer);

extern template int ProtolPostMessage(const TCHAR                             *pUrlPath,
                                      ProtocolRequest<ReqGetUserCfgParams>    *pReq,
                                      ProtocolResponse<RspUsrCliConfigParams> *pRsp,
                                      bool                                     platformServer);

extern template int ProtolPostMessage(const TCHAR                              *pUrlPath,
                                      ProtocolRequest<ReqUserSetCliCfgParams>  *pReq,
                                      ProtocolResponse<RspUserSetCliCfgParams> *pRsp,
                                      bool                                      platformServer);

extern template int ProtolPostMessage(const TCHAR                           *pUrlPath,
                                      ProtocolRequest<ReqStartTunnelParams> *pReq,
                                      ProtocolResponse<ResponseStatus>      *pRsp,
                                      bool                                   platformServer);

extern template int ProtolPostMessage(const TCHAR                      *pUrlPath,
                                      ProtocolRequest<ReqHeartParams>  *pReq,
                                      ProtocolResponse<RspHeartParams> *pRsp,
                                      bool                              platformServer);

#if !USER_REAL_PLATFORM
template<class T1, class T2> int PlatformProtolPostMessage(const TCHAR *pUrlPath, T1 *pReq, T2 *pRsp);

extern template int PlatformProtolPostMessage(const TCHAR                *pUrlPath,
                                              PlatformReqServerCfgParms  *pReq,
                                              PlatformRspServerCfgParams *pRsp);

extern template int PlatformProtolPostMessage(const TCHAR                *pUrlPath,
                                              PlatformReqClientCfgParms  *pReq,
                                              PlatformRspClientCfgParams *pRsp);

#if 0
template<class T1> int PlatformProtolGetMessage(const TCHAR *pUrlPath, T1 *pRsp);

extern template int PlatformProtolGetMessage(const TCHAR                *pUrlPath,
                                              PlatformRspUserClientCfgParams *pRsp);
#endif
#endif