//go:build windows

package yu_hpsocket

import (
	yu_proxy "gogs.qqck.cn/s/tools/proxy"
	yu_sys "gogs.qqck.cn/s/tools/sys"
)

// Client
//
//	@Description: Client 系列组件底层实现
type Client[T any] struct {
	hListener uintptr
	hClient   uintptr
	SSL       bool
	Extra     any // 附加数据

	// exdata----------------------------------

	socket uintptr

	// 事件----------------------------------

	onPrepareConnect func(t *T, Sender, ConnID, socket uintptr) HR
	onConnect        func(t *T, Sender, ConnID uintptr) HR
	onHandShake      func(t *T, Sender, ConnID uintptr) HR
	onSend           func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR
	onReceive        func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR
	onClose          func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR

	// 扩展----------------------------------------------------------------

	_RemoteAddress string
	_Port          int

	proxy_info    *yu_proxy.Info
	proxy_connect bool
}

// isValid
//
//	@Description: 对象是否有效
func (t *Client[T]) isValid() bool {
	return t.hListener != 0 && t.hClient != 0
}

// Start
//
//	@Description: 启动通信组件（并指定【可选】绑定地址）
//	@param RemoteAddress 服务端地址
//	@param Port 服务端端口
//	@param AsyncConnect 是否采用异步 Connect
//	@param BindAddress 绑定地址（默认：nullptr，TcpClient/UdpClient -> 不执行绑定操作，UdpCast 绑定 -> 0.0.0.0）
//	@param LocalPort 本地端口（默认：0）
//	@return bool 是否启动成功
func (t *Client[T]) Start(RemoteAddress string, Port int, AsyncConnect bool, BindAddress string, LocalPort int) bool {
	if !t.isValid() {
		return false
	}
	// -------------------------------------------------------------------------------关联必要事件
	if t.onPrepareConnect == nil {
		t.OnPrepareConnect(func(t *T, Sender, ConnID, socket uintptr) HR {
			return HR_IGNORE
		})
	}
	// -------------------------------------------------------------------------------关联必要事件------end
	if t.proxy_info.Host == "" {
		return HP_Client_StartWithBindAddressAndLocalPort.CallBool(t.hClient,
			yu_sys.S{yu_sys.Gbk, RemoteAddress}, Port,
			AsyncConnect,
			yu_sys.S{yu_sys.Gbk, BindAddress}, LocalPort,
		)
	}
	// -------------------------------------------------------------------------------判断代理是否有效
	if !t.proxy_info.IsValid() || t.proxy_info.IsTimeout() {
		return false
	}

	// -------------------------------------------------------------------------------关联必要事件
	if t.onConnect == nil {
		t.OnConnect(func(t *T, Sender, ConnID uintptr) HR {
			return HR_IGNORE
		})
	}
	// -------------------------------------------------------------------------------关联必要事件------end
	t._RemoteAddress, t._Port = RemoteAddress, Port
	return HP_Client_StartWithBindAddressAndLocalPort.CallBool(t.hClient,
		yu_sys.S{yu_sys.Gbk, t.proxy_info.Host}, t.proxy_info.Port,
		AsyncConnect,
		yu_sys.S{yu_sys.Gbk, BindAddress}, LocalPort,
	)
}

// Stop
//
//	@Description: 关闭客户端通信组件，关闭完成后断开与服务端的连接并释放所有资源
//	@return bool 是否成功关闭
func (t *Client[T]) Stop() bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_Stop.CallBool(t.hClient)
}

// Wait
//
//	@Description: 等待通信组件停止运行
//	@param Milliseconds 超时时间（毫秒，默认：-1，永不超时）
//	@return bool 超时返回 false
func (t *Client[T]) Wait(Milliseconds int) bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_Wait.CallBool(t.hClient, Milliseconds)
}

// Send
//
//	@Description: 向服务端发送数据
//	@param buf 欲发送的数据
//	@return bool 是否发送成功
func (t *Client[T]) Send(buf []byte) bool {
	if !t.isValid() {
		return false
	}
	if len(buf) == 0 {
		return true
	}
	return HP_Client_Send.CallBool(t.hClient, buf, len(buf))
}

// SendS
//
//	@Description: 向服务端发送数据
//	@param buf 欲发送的数据
//	@return bool 是否发送成功
func (t *Client[T]) SendS(buf string) bool {
	if !t.isValid() {
		return false
	}
	if len(buf) == 0 {
		return true
	}
	return HP_Client_Send.CallBool(t.hClient, buf, len(buf))
}

// IsSecure
//
//	@Description: 检测是否为安全连接（SSL/HTTPS）
func (t *Client[T]) IsSecure() bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_IsSecure.CallBool(t.hClient)
}

// SetExtra
//
//	@Description: 设置连接的附加数据
func (t *Client[T]) SetExtra(extra uintptr) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_Client_SetExtra.Call(t.hClient, extra)
	return t
}

// GetExtra
//
//	@Description: 获取连接的附加数据
func (t *Client[T]) GetExtra() uintptr {
	if !t.isValid() {
		return 0
	}
	return HP_Client_GetExtra.CallUintptr(t.hClient)
}

// HasStarted
//
//	@Description: 检查通信组件是否已启动
func (t *Client[T]) HasStarted() bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_HasStarted.CallBool(t.hClient)
}

// GetState
//
//	@Description: 查看通信组件当前状态，SS_ 开头常量
func (t *Client[T]) GetState() SS {
	if !t.isValid() {
		return SS_STOPPED
	}
	return SS(HP_Client_GetState.CallUintptr(t.hClient))
}

// GetLastError
//
//	@Description: 获取最近一次失败操作的错误代码
func (t *Client[T]) GetLastError() int {
	if !t.isValid() {
		return 0
	}
	return HP_Client_GetLastError.CallInt(t.hClient)
}

// GetLastErrorDesc
//
//	@Description: 获取最近一次失败操作的错误描述
func (t *Client[T]) GetLastErrorDesc() string {
	if !t.isValid() {
		return "Not Object"
	}
	return HP_Client_GetLastErrorDesc.CallGbkToUtf8(t.hClient)
}

// GetConnectionID
//
//	@Description: 获取该组件对象的连接 ID
func (t *Client[T]) GetConnectionID() uintptr {
	if !t.isValid() {
		return 0
	}
	return HP_Client_GetConnectionID.CallUintptr(t.hClient)
}

// GetLocalAddress
//
//	@Description: 获取连接的本地绑定信息
func (t *Client[T]) GetLocalAddress() (address string, port int) {
	if !t.isValid() {
		return
	}
	j_address_len := 128
	j_address := make([]byte, 64)
	if !HP_Client_GetLocalAddress.CallBool(t.hClient, j_address, &j_address_len, &port) {
		return
	}
	j_address_len -= 1 // 有结束符 {0}
	j_unicode_len := j_address_len * 2
	j_unicode := make([]byte, j_unicode_len)
	yu_sys.MultiByteToWideChar.Call(936, 0, j_address, j_address_len, j_unicode, j_unicode_len)

	j_utf8_size := j_unicode_len * 2
	j_utf8 := make([]byte, j_utf8_size)
	address = string(j_utf8[:yu_sys.WideCharToMultiByte.CallInt(65001, 0, j_unicode, j_address_len, j_utf8, j_utf8_size, 0, 0)])
	return
}

// GetRemoteHost
//
//	@Description: 获取连接的远程主机信息
func (t *Client[T]) GetRemoteHost() (address string, port int) {
	if !t.isValid() {
		return
	}
	j_address_len := 128
	j_address := make([]byte, 64)
	if !HP_Client_GetRemoteHost.CallBool(t.hClient, j_address, &j_address_len, &port) {
		return
	}
	j_address_len -= 1 // 有结束符 {0}
	j_unicode_len := j_address_len * 2
	j_unicode := make([]byte, j_unicode_len)
	yu_sys.MultiByteToWideChar.Call(936, 0, j_address, j_address_len, j_unicode, j_unicode_len)

	j_utf8_size := j_unicode_len * 2
	j_utf8 := make([]byte, j_utf8_size)
	address = string(j_utf8[:yu_sys.WideCharToMultiByte.CallInt(65001, 0, j_unicode, j_address_len, j_utf8, j_utf8_size, 0, 0)])
	return
}

// GetPendingDataLength
//
//	@Description: 获取连接中未发出数据的长度
func (t *Client[T]) GetPendingDataLength() (length int) {
	if !t.isValid() {
		return
	}
	HP_Client_GetPendingDataLength.Call(t.hClient, &length)
	return
}

// SetFreeBufferPoolSize
//
//	@Description: 设置内存块缓存池大小（通常设置为 -> PUSH 模型：5 - 10；PULL 模型：10 - 20 ）
func (t *Client[T]) SetFreeBufferPoolSize(FreeBufferPoolSize int) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_Client_SetFreeBufferPoolSize.Call(t.hClient, FreeBufferPoolSize)
	return t
}

// SetFreeBufferPoolHold
//
//	@Description: 设置内存块缓存池回收阀值（通常设置为内存块缓存池大小的 3 倍）
func (t *Client[T]) SetFreeBufferPoolHold(FreeBufferPoolHold int) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_Client_SetFreeBufferPoolHold.Call(t.hClient, FreeBufferPoolHold)
	return t
}

// GetFreeBufferPoolSize
//
//	@Description: 获取内存块缓存池大小
func (t *Client[T]) GetFreeBufferPoolSize() int {
	if !t.isValid() {
		return 0
	}
	return HP_Client_GetFreeBufferPoolSize.CallInt(t.hClient)
}

// GetFreeBufferPoolHold
//
//	@Description: 获取内存块缓存池回收阀值
func (t *Client[T]) GetFreeBufferPoolHold() int {
	if !t.isValid() {
		return 0
	}
	return HP_Client_GetFreeBufferPoolHold.CallInt(t.hClient)
}

// SetupSSLContext
//
//	@Description: 初始化通信组件 SSL环境参数，SSL环境参数必须在 SSL通信组件启动前完成初始化，否则启动失败
//	@param VerifyMode SSL_VM_ 开头常量，SSL验证模式
//	@param PemCertFile 证书文件
//	@param PemKeyFile 私钥文件
//	@param KeyPasswod 私钥密码（没有密码则为空）
//	@param CAPemCertFileOrPath CA 证书文件或目录（单向验证或客户端可选）
func (t *Client[T]) SetupSSLContext(VerifyMode SSL_VM, PemCertFile, PemKeyFile, KeyPasswod, CAPemCertFileOrPath string) bool {
	if !t.isValid() {
		return false
	}
	return HP_SSLClient_SetupSSLContext.CallBool(t.hClient, uintptr(VerifyMode),
		yu_sys.S{yu_sys.Gbk, PemCertFile}, yu_sys.S{yu_sys.Gbk, PemKeyFile},
		yu_sys.S{yu_sys.Gbk, KeyPasswod}, yu_sys.S{yu_sys.Gbk, CAPemCertFileOrPath},
	)
}

// SetupSSLContextByMemory
//
//	@Description: 初始化通信组件 SSL环境参数，SSL环境参数必须在 SSL通信组件启动前完成初始化，否则启动失败
//	@param VerifyMode SSL_VM_ 开头常量，SSL验证模式
//	@param PemCert 证书内容
//	@param PemKey 私钥内容
//	@param KeyPasswod 私钥密码（没有密码则为空）
//	@param CAPemCert CA 证书内容（单向验证可选）
func (t *Client[T]) SetupSSLContextByMemory(VerifyMode SSL_VM, PemCert, PemKey, KeyPasswod, CAPemCert string) bool {
	if !t.isValid() {
		return false
	}
	return HP_SSLClient_SetupSSLContextByMemory.CallBool(t.hClient, uintptr(VerifyMode),
		yu_sys.S{yu_sys.Gbk, PemCert}, yu_sys.S{yu_sys.Gbk, PemKey},
		yu_sys.S{yu_sys.Gbk, KeyPasswod}, yu_sys.S{yu_sys.Gbk, CAPemCert},
	)
}

// CleanupSSLContext
//
//	@Description: 清理通信组件 SSL运行环境，回收 SSL相关内存
func (t *Client[T]) CleanupSSLContext() *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_SSLClient_CleanupSSLContext.Call(t.hClient)
	return t
}

// StartSSLHandShake
//
//	@Description: 启动 SSL握手，当通信组件设置为非自动握手时，需要调用本方法启动 SSL握手
func (t *Client[T]) StartSSLHandShake() bool {
	if !t.isValid() {
		return false
	}
	return HP_SSLClient_StartSSLHandShake.CallBool(t.hClient)
}

// SetSSLAutoHandShake
//
//	@Description: 设置通信组件握手方式（默认：true，自动握手）
func (t *Client[T]) SetSSLAutoHandShake(AutoHandShake bool) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_SSLClient_SetSSLAutoHandShake.Call(t.hClient, AutoHandShake)
	return t
}

// IsSSLAutoHandShake
//
//	@Description: 获取通信组件握手方式
func (t *Client[T]) IsSSLAutoHandShake() bool {
	if !t.isValid() {
		return false
	}
	return HP_SSLClient_IsSSLAutoHandShake.CallBool(t.hClient)
}

// SetSSLCipherList
//
//	@Description: 设置 SSL加密算法列表
func (t *Client[T]) SetSSLCipherList(CipherList string) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_SSLClient_SetSSLCipherList.Call(t.hClient, yu_sys.S{yu_sys.Gbk, CipherList})
	return t
}

// GetSSLCipherList
//
//	@Description: 获取 SSL加密算法列表
func (t *Client[T]) GetSSLCipherList() string {
	if !t.isValid() {
		return ""
	}
	return HP_SSLClient_GetSSLCipherList.CallGbkToUtf8(t.hClient)
}

// GetSSLSessionInfo
//
//	@Description: 获取指定类型的 SSLSession 信息（输出类型参考：SSL_SSI_）
//	@param enInfo SSL_SSI_ 开头常量
func (t *Client[T]) GetSSLSessionInfo(enInfo SSL_SSI) (Info uintptr) {
	if !t.isValid() {
		return
	}
	HP_SSLClient_GetSSLSessionInfo.Call(t.hClient, uintptr(enInfo), &Info)
	return
}

// IsPauseReceive
//
//	@Description: 获取连接的数据接收状态
func (t *Client[T]) IsPauseReceive() (Paused bool) {
	if !t.isValid() {
		return
	}
	HP_Client_IsPauseReceive.Call(t.hClient, &Paused)
	return
}

// IsConnected
//
//	@Description: 检测是否有效连接
func (t *Client[T]) IsConnected() bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_IsConnected.CallBool(t.hClient)
}

// SetReuseAddressPolicy
//
//	@Description: 设置地址重用选项
//	@param enReusePolicy RAP_ 开头常量
func (t *Client[T]) SetReuseAddressPolicy(ReusePolicy RAP) *Client[T] {
	if !t.isValid() {
		return t
	}
	HP_Client_SetReuseAddressPolicy.Call(t.hClient, uintptr(ReusePolicy))
	return t
}

// GetReuseAddressPolicy
//
//	@Description: 获取地址重用选项 RAP_ 开头常量
func (t *Client[T]) GetReuseAddressPolicy() RAP {
	if !t.isValid() {
		return RAP_NONE
	}
	return RAP(HP_Client_GetReuseAddressPolicy.CallUintptr(t.hClient))
}

// PauseReceive
//
//	@Description: 暂停/恢复某个连接的数据接收工作
func (t *Client[T]) PauseReceive(Paused bool) bool {
	if !t.isValid() {
		return false
	}
	return HP_Client_PauseReceive.CallBool(t.hClient, Paused)
}

// OnPrepareConnect
//
//	@Description: 【可选】绑定准备连接事件
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnPrepareConnect(call func(t *T, Sender, ConnID, socket uintptr) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnPrepareConnect.Call(t.hListener, 0)
	} else {
		t.onPrepareConnect = call
		HP_Set_FN_Client_OnPrepareConnect.Call(t.hListener, client_callback_OnPrepareConnect_ptr)
	}
	return t
}

// OnConnect
//
//	@Description: 【可选】绑定连接事件
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnConnect(call func(t *T, Sender, ConnID uintptr) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnConnect.Call(t.hListener, 0)
	} else {
		t.onConnect = call
		HP_Set_FN_Client_OnConnect.Call(t.hListener, client_callback_OnConnect_ptr)
	}
	return t
}

// OnHandShake
//
//	@Description: 【可选】绑定握手事件
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnHandShake(call func(t *T, Sender, ConnID uintptr) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnHandShake.Call(t.hListener, 0)
	} else {
		t.onHandShake = call
		HP_Set_FN_Client_OnHandShake.Call(t.hListener, client_callback_OnHandShake_ptr)
	}
	return t
}

// OnSend
//
//	@Description: 【可选】绑定发送事件
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnSend(call func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnSend.Call(t.hListener, 0)
	} else {
		t.onSend = call
		HP_Set_FN_Client_OnSend.Call(t.hListener, client_callback_OnSend_ptr)
	}
	return t
}

// OnReceive
//
//	@Description: 【必选】绑定数据接收事件
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnReceive(call func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnReceive.Call(t.hListener, 0)
	} else {
		t.onReceive = call
		HP_Set_FN_Client_OnReceive.Call(t.hListener, client_callback_OnReceive_ptr)
	}
	return t
}

// OnClose
//
//	@Description: 【必选】绑定断开事件
//	@param call->Operation 通过该参数标识是哪种操作导致的错误 SO_ 开头常量
//	@param call->return HR_ 开头常量
func (t *Client[T]) OnClose(call func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR) *Client[T] {
	if !t.isValid() {
		return t
	}
	if call == nil {
		HP_Set_FN_Client_OnClose.Call(t.hListener, 0)
	} else {
		t.onClose = call
		HP_Set_FN_Client_OnClose.Call(t.hListener, client_callback_OnClose_ptr)
	}
	return t
}

// OnDefault
//
//	@Description: 【可选】绑定所有【必选】事件
func (t *Client[T]) OnDefault() *Client[T] {
	if !t.isValid() {
		return t
	}
	if t.onReceive == nil {
		t.OnReceive(func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR {
			return HR_OK
		})
	}
	if t.onClose == nil {
		t.OnClose(func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR {
			return HR_OK
		})
	}
	return t
}
