//go:build windows

package yu_hpsocket

import (
	"sync"
	"syscall"
)

func init() {
	client_callback_OnPrepareConnect_ptr = syscall.NewCallback(client_callback_OnPrepareConnect)
	client_callback_OnConnect_ptr = syscall.NewCallback(client_callback_OnConnect)
	client_callback_OnHandShake_ptr = syscall.NewCallback(client_callback_OnHandShake)
	client_callback_OnSend_ptr = syscall.NewCallback(client_callback_OnSend)
	client_callback_OnReceive_ptr = syscall.NewCallback(client_callback_OnReceive)
	client_callback_OnClose_ptr = syscall.NewCallback(client_callback_OnClose)
}

var (
	client_callback_OnPrepareConnect_ptr uintptr
	client_callback_OnConnect_ptr        uintptr
	client_callback_OnHandShake_ptr      uintptr
	client_callback_OnSend_ptr           uintptr
	client_callback_OnReceive_ptr        uintptr
	client_callback_OnClose_ptr          uintptr
)

func client_callback_OnPrepareConnect(Sender, ConnID, socket uintptr) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		t.socket = socket
		return t.onPrepareConnect(t, Sender, ConnID, socket)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		t.socket = socket
		return t.onPrepareConnect(t, Sender, ConnID, socket)
	}
	return HR_OK
}

func client_callback_OnConnect(Sender, ConnID uintptr) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		if t.proxy_info.IsValid() && !t.connect_proxy() {
			return HR_ERROR
		}
		return t.onConnect(t, Sender, ConnID)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		if t.proxy_info.IsValid() && !t.connect_proxy() {
			return HR_ERROR
		}
		return t.onConnect(t, Sender, ConnID)
	}
	return HR_OK
}

func client_callback_OnHandShake(Sender, ConnID uintptr) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		return t.onHandShake(t, Sender, ConnID)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		return t.onHandShake(t, Sender, ConnID)
	}
	return HR_OK
}

func client_callback_OnSend(Sender, ConnID, Data uintptr, Length uintptr) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		return t.onSend(t, Sender, ConnID, Data, Length)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		return t.onSend(t, Sender, ConnID, Data, Length)
	}
	return HR_OK
}

func client_callback_OnReceive(Sender, ConnID, Data uintptr, Length uintptr) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		return t.onReceive(t, Sender, ConnID, Data, Length)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		return t.onReceive(t, Sender, ConnID, Data, Length)
	}
	return HR_OK
}

func client_callback_OnClose(Sender, ConnID uintptr, Operation SO, ErrorCode int) HR {
	switch j_item := _client_on_get(Sender); j_item._type {
	case _client_type_TcpClient:
		t := j_item.t.(*TcpClient)
		return t.onClose(t, Sender, ConnID, Operation, ErrorCode)
	case _client_type_TcpPackClient:
		t := j_item.t.(*TcpPackClient)
		return t.onClose(t, Sender, ConnID, Operation, ErrorCode)
	}
	return HR_OK
}

// ---------------------------------------------------------------------------------------------------------------------

var _client_on_lock sync.Mutex
var _client_on = make(map[uintptr]any)

const (
	_client_type_Client = iota
	_client_type_TcpClient
	_client_type_TcpPackClient
)

type _client_item struct {
	_type byte
	t     any
}

func _client_on_set(Sender uintptr, v *_client_item) {
	_client_on_lock.Lock()
	defer _client_on_lock.Unlock()
	_client_on[Sender] = v
}

func _client_on_get(Sender uintptr) *_client_item {
	_client_on_lock.Lock()
	defer _client_on_lock.Unlock()
	if j_v, j_is := _client_on[Sender]; j_is {
		return j_v.(*_client_item)
	}
	return nil
}

func _client_on_del(Sender uintptr) {
	_client_on_lock.Lock()
	defer _client_on_lock.Unlock()
	delete(_client_on, Sender)
}
