#pragma once

#include <Windows.h>

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

/**
 * @brief WireGuard key 最大长度
 */
constexpr auto WG_KEY_MAX = (64);

/**
 * @brief 操作系统最大网卡数
 */
#define NET_CARD_MAX (32)

/**
 * @brief IP 字符串最大长度(支持IPv6)
 */
#define MAX_IP_LEN   (48)

/**
 * @brief 协议加密类型
 * 
 */
typedef enum {
    CRYPTO_NONE   = 0,    ///< 不加密
    CRYPTO_BASE64 = 1,    ///< BASE64 字符串编码
    CRYPTO_AES128 = 2,    ///< AES 128位秘钥 加密
    CRYPTO_3DES   = 3,    ///< 3DES 加密
    CRYPTO_AES256 = 4,    ///< AES 256 位秘钥加密
    CRYPTO_MAX,
} PROTO_CRYPTO_TYPE;

/**
 * @brief 日志等级
 * 
 */
enum LOG_LEVEL {
    LOG_TRACE = 0,    ///< TRACE 日志等级
    LOG_DEBUG,        ///< DEBUG 日志等级
    LOG_INFO,         ///< INFO  日志等级
    LOG_WARN,         ///< WARN  日志等级
    LOG_ERROR,        ///< ERROR 日志等级
    LOG_CRITICAL,     ///< CRITICAL 日志等级
    LOG_OFF           ///< 关闭日志
};

/** 
 *
 * @brief 本地计算机网卡信息
 */
typedef struct {
    int   InterfaceIndex;                ///< 网卡索引
    TCHAR NetCardUUID[260];              ///< 网卡名称, Windows标识为 UUID
    TCHAR NetCardDescription[132];       ///< 网卡描述
    TCHAR NetCardIpaddr[MAX_IP_LEN];     ///< 网卡 IP 地址
    TCHAR NetCardNetmask[MAX_IP_LEN];    ///< 网卡子网掩码
    TCHAR NetCardGateway[MAX_IP_LEN];    ///< 网卡网关
    TCHAR NetCardMacAddr[20];            ///< 网卡 MAC 地址
} NIC_CONTENT, *PNIC_CONTENT;

/**
 * @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 初始化 SDK 运行环境
 * @param[in] pWorkDir  程序工作路径,如果不设置系统自动获取
 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO 
 * - -ERR_ITEM_EXISTS 未找到 WireGuard 程序
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl TunnelSDKInitEnv(const TCHAR *pWorkDir);

/**
 * @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[in] pLogFile  日志文件名称/完整路径
 * @param[in] level     日志最低有效等级
 */
TUNNEL_API void __cdecl InitTunnelSDKLog(const TCHAR *pLogFile, LOG_LEVEL level);

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

/**
 * @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);

/**
 * @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 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 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[in] bInstall TRUE 安装服务, FALSE 卸载服务
 * @return  函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO 
 */
TUNNEL_API int __cdecl WireGuardInstallServerService(bool bInstall);

/**
 * @brief 清理 SDK 运行资源
 */
TUNNEL_API void __cdecl TunnelSDKUnInit();
/**
 * @brief 获取本机网卡信息
 * @param[in,out] pInfo 网卡信息 @see NIC_CONTENT
 * @param[out] pItemCounts 计算机当前操作系统中网卡总数 最大值 32
 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts);

/**
 * @brief 获取网卡接口索引编号
 * @param pInterfaceName 网卡名称
 * @param pIndex 网卡索引
 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - -ERR_MEMORY_STR 字符串处理
 * - -ERR_CALL_SHELL 调用系统命令行失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl GetInterfaceIndexByName(const TCHAR *pInterfaceName, int *pIndex);

/**
 * @brief 删除接口网络地址
 * @param pInterfaceName 网卡名称
 * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
 * - -ERR_INPUT_PARAMS 输入参数错误
 * - -ERR_MALLOC_MEMORY 分配内存失败
 * - -ERR_MEMORY_STR 字符串处理
 * - -ERR_CALL_SHELL 调用系统命令行失败
 * - ERR_SUCCESS 成功
 */
TUNNEL_API int __cdecl RemoveInterfaceIpAddress(const TCHAR *pInterfaceName);

TUNNEL_API int __cdecl SetInterfaceIpAddressFromCIDR(const TCHAR *pInterfaceName, const TCHAR *pCidrIpaddr);
#ifdef __cplusplus
}
#endif