#pragma once

#include "common.h"
#include <Windows.h>

#ifdef NETTUNNELSDK_EXPORTS
#define TUNNEL_API __declspec(dllexport)
#else
#define TUNNEL_API __declspec(dllimport)
#endif

/**
 * @brief 网络共享模式
 * 
 */
typedef enum {
    ICS_SHARE_MODE = 0,    ///< Internet Share Mode(ICS) 模式
    NAT_SHARE_MODE = 1     ///< Net Address Translation(NAT) 模式
} NET_SHARE_MODE;

typedef struct {
    CHECK_FUNCTION chk;
    bool           result;
    TCHAR          errMsg[MAX_PATH];
} CHK_RESULT, *PCHK_RESULT;

/**
 * @brief WireGuard 服务端配置信息
 */
typedef struct {
    TCHAR Name[64];          ///< WireGuard 网卡名称
    TCHAR Address[32];       ///< WireGuard 本地网络IP地址
    TCHAR PrivateKey[64];    ///< WireGuard 本机私钥
    int   ListenPort;        ///< WireGuard 服务端监听端口

    // 根据系统设计，不支持多个客户端同时连接
    TCHAR CliPubKey[64];    ///< WireGuard 客户端公钥
    TCHAR AllowNet[256];    ///< WireGuard 允许对端访问本地网络的配置
} WGSERVER_CONFIG, *PWGSERVER_CONFIG;

/**
 * @brief WireGuard 客户端配置信息
 */
typedef struct {
    TCHAR Name[64];          ///< WireGuard 网卡名称
    TCHAR PrivateKey[64];    ///< WireGuard 本机私钥
    TCHAR Address[32];       ///< WireGuard 本地网络IP地址

    // Peer Server
    TCHAR SvrPubKey[64];     ///< WireGuard 服务端公钥
    TCHAR AllowNet[256];     ///< WireGuard 允许对端访问本地网络的配置
    TCHAR ServerURL[256];    ///< WireGuard 服务端IP地址和端口
} WGCLIENT_CONFIG, *PWGCLIENT_CONFIG;

#ifdef __cplusplus    // If used by C++ code,
extern "C" {
// we need to export the C interface
#endif

/**
 * @brief 获取当前网络共享模式
 * @return 当前网络共享模式 @see NET_SHARE_MODE
 */
TUNNEL_API NET_SHARE_MODE __cdecl GetCurrentNetShareMode();

/**
 * @brief 设置获取当前网络共享模式
 * @param shareMode 网络共享模式 @see NET_SHARE_MODE
 */
TUNNEL_API void __cdecl SetCurrentNetShareMode(NET_SHARE_MODE shareMode);

/**
 * @brief 初始化 SDK 运行环境
 * @param[in] pWorkDir  程序工作路径，如果不设置系统自动获取
 * @param[in] pSvrUrl 管理平台 URL 地址 example: http://localhost:2313, https://localhost:2313
 * @param[in] pLogFile  日志文件名称/完整路径
 * @param[in] level     日志最低有效等级
 * @param[in] isWorkServer  SDK 工作模式
 * - TRUE 服务端
 * - FALSE 客户端
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO 
 * - -ERR_ITEM_EXISTS 未找到 WireGuard 程序
 * - -ERR_SYS_CALL 获取配置本地配置文件存储目录失败
 * - -ERR_CREATE_FILE 创建用户配置文件目录失败
 * - -ERR_ITEM_UNEXISTS WireGuard 未安装
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl TunnelSDKInitEnv(const TCHAR *pWorkDir,
                                        const TCHAR *pSvrUrl,
                                        const TCHAR *pLogFile,
                                        LOG_LEVEL    level,
                                        bool         isWorkServer);

/**
 * @brief 设置传输协议加密方式，默认 CRYPTO_NONE
 * @param[in] type 协议加密类型 @see PROTO_CRYPTO_TYPE
 * @param[in] pProKey 加密秘钥，CRYPTO_NONE， CRYPTO_BASE64 无效忽略
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, const TCHAR *pProKey);

/**
 * @brief 打开/关闭 SDK 日志开关
 * @param enLog 日志开关
 * - TRUE   打开日志
 * - FALSE  关闭日志
 */
TUNNEL_API void __cdecl TunnelLogEnable(bool enLog);

/**
 * @brief 创建 WireGuard 密钥对
 * @param[out] pPubKey 公钥缓冲区
 * @param[in] pubkeySize 公钥缓冲区大小(字节数)
 * @param[out] pPrivKey 私钥缓冲区
 * @param[in] privKeySize 私钥缓冲区大小(字节数)
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_ITEM_UNEXISTS WireGuard 未配置或未安装
 * - -ERR_CALL_SHELL 调用操作系统命令行工具失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, int privKeySize);

/**
 * @brief 创建 WireGuard 服务端配置文件
 * @param[in] pWgConfig 配置文件相关配置项 @see WGSERVER_CONFIG
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - -ERR_OPEN_FILE 打开文件失败
 * - -ERR_MEMORY_STR 字符串处理失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig);

/**
 * @brief 创建 WireGuard 客户端配置文件
 * @param[in] pWgConfig 配置文件相关配置项 @see WGCLIENT_CONFIG
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - -ERR_OPEN_FILE 打开文件失败
 * - -ERR_MEMORY_STR 字符串处理失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig);

/**
 * @brief 通过 WireGuard 配置文件安装隧道服务
 * @param pInterfaceName 隧道服务名
 * @param pWGConfigFilePath 配置文件完整路径
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_ITEM_UNEXISTS 找不掉对应的服务
 * - -ERR_OPEN_SCM 打开服务管理器设备失败
 * - -ERR_OPEN_SERVICE 打开服务失败
 * - -ERR_CREATE_SERVICE 创建服务失败
 * - -ERR_CONFIG_SERVICE 配置服务失败
 * - -ERR_START_SERVICE  停止服务失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl CreateWireGuardService(const TCHAR *pInterfaceName, const TCHAR *pWGConfigFilePath);

/**
 * @brief 获取当前 WireGuard 服务隧道是否正则运行
 * @param pTunnelName 隧道服务名
 * @param pIsRunning pIsRunning WireGuard 服务隧道运行状态
 * - TRUE 已经安装
 * - FALSE 未安装
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_OPEN_SCM 打开服务管理器设备失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl GetWireGuardServiceStatus(const TCHAR *pTunnelName, bool *pIsRunning);

/**
 * @brief 移除 WireGuard 隧道服务
 * @param pTunnelName  隧道服务名
 * @param bIsWaitStop  是否等待隧道服务结束 TRUE: 等待服务结束, FALSE: 不等待直接结束
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_OPEN_SCM 打开服务管理器设备失败
 * - -ERR_OPEN_SERVICE 打开服务失败
 * - -ERR_STOP_SERVICE  停止服务失败
 * - -ERR_DELETE_SERVICE 删除服务失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl RemoveGuardService(const TCHAR *pTunnelName, bool bIsWaitStop);

/**
 * @brief 安装/卸载 WireGuard 服务
 * @param[in] bInstall TRUE 安装服务, FALSE 卸载服务
 * @return  函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO 
 */
TUNNEL_API int __cdecl WireGuardInstallDefaultServerService(bool bInstall);

/**
 * @brief 通过 WireGuard 配置文件安装隧道服务
 * @param[in] pTunnelCfgPath 配置文件完整路径
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_ITEM_UNEXISTS 配置文件不存在
 * - -ERR_CALL_SHELL 调用 WireGuard 外部服务失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl WireGuardInstallServerService(const TCHAR *pTunnelCfgPath);

/**
 * @brief 卸载 WireGuard 隧道服务
 * @param[in] pTunnelName 隧道服务名
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_ITEM_UNEXISTS 配置文件不存在
 * - -ERR_CALL_SHELL 调用 WireGuard 外部服务失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl WireGuardUnInstallServerService(const TCHAR *pTunnelName);

/**
 * @brief 判断当前网络服务工作模式 客户端/服务端
 * @param[out] pIsWorkServer 工作模式
 * - TRUE 服务端
 * - FALSE 客户端
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl GetWireGuardWorkMode(bool *pIsWorkServer);

/**
 * @brief 获取当前 WireGuard 服务是否安装
 * @param[out] pIsInstalled WireGuard 服务安装状态
 * - TRUE 已经安装
 * - FALSE 未安装
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_OPEN_SCM,           打开服务管理器设备
 * - -ERR_OPEN_SERVICE,       打开服务失败
 * - -ERR_GET_SERVICESSTATUS, 获取服务状态失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl IsWireGuardServerInstalled(bool *pIsInstalled);

/**
 * @brief 获取当前 WireGuard 服务隧道是否正则运行
 * @param[in] pIfName WireGuard 隧道网络接口名称
 * @param[out] pIsRunning WireGuard 服务隧道运行状态
 * - TRUE 已经安装
 * - FALSE 未安装
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning);

/**
 * @brief 清理 SDK 运行资源
 */
TUNNEL_API void __cdecl TunnelSDKUnInit();

/**
 * @brief SCG 代理服务开关
 * @param isEnable TRUE: 启动 SCG 代理, FALSE: 禁用 SCG 代理
 */
TUNNEL_API void __cdecl EnableSCGProxy(bool isEnable);

/**
 * @brief 获取当前 SCG 代理服务状态
 * @return TRUE: SCG 代理启动, FALSE: SCG 代理禁用
 */
TUNNEL_API bool __cdecl GetSCGProxyStatus();

/**
 * @brief 计算文件 Hash
 * @param[in] type  Hash 类型 @see HASH_TYPE
 * @param[in] pPath 需要计算 Hash 值的文件路径
 * @param[out] outHash 计算结果
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_ITEM_UNEXISTS 文件不存在
 * - -ERR_OPEN_FILE 打开文件失败
 * - -ERR_BCRYPT_OPEN 创建加解密算法失败
 * - -ERR_BCRYPT_GETPROPERTY 获取加解密算法属性失败
 * - -ERR_BCRYPT_CREATEHASH 创建 Hash 算法失败
 * - -ERR_BCRYPT_HASHDATA 计算 Hash 数据失败
 * - -ERR_BCRYPT_FINISHHASH 计算 Hash 结果失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl CalcFileHash(const HASH_TYPE type, const TCHAR *pPath, TCHAR outHash[]);

//+++++++++++++++++++++++++++++++++++++++++Temp Interface

//TUNNEL_API int __cdecl ProtoGetUserConfigure(const TCHAR *pUser, const TCHAR *pToken);
//TUNNEL_API const TCHAR* __cdecl GetInterfaceGUIDByName(const TCHAR *pInterfaceName, GUID* pGuid);
//------------------------------------------End Temp Interface
#if 0
/**
 * @brief 安装 Windows NAT 自定义 PowerShell 命令
 * @return 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_OPEN_FILE 打开文件失败
 * - -ERR_MEMORY_STR 字符串处理
 * - -ERR_ITEM_UNEXISTS 资源不存在
 * - -ERR_CALL_SHELL 调用系统命令行失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl InstallWindowsNATCommand();
TUNNEL_API int __cdecl WireGuardNetConnectionSharingEnable();


/**
 * @brief 查找 WireGuard 运行环境
 * @param[out] pFullPath wireguard.exe 程序路径
 * @param[in] maxSize pFullPath 缓冲区最大字节数
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - -ERR_FILE_NOT_EXISTS 文件不存在
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl FindWireguardExe(TCHAR *pFullPath, int maxSize);

/**
 * @brief 设置 wireguard.exe 程序路径
 * @param[in] pPath wireguard.exe 程序路径
 * @return 函数执行结果 0: 成功， 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_ITEM_UNEXISTS 文件不存在
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl SetWireguardPath(const TCHAR *pPath);
#endif
#ifdef __cplusplus
}
#endif