#pragma once
#include "ProtocolBase.h"

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)
};

#define GET_CLIENTCFG_PATH     TEXT("/tunnel/getuserconfig")
#define GET_SERVERCFG_PATH     TEXT("/tunnel/getserverconfig")

#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 = true);

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);