//go:build windows

package yu_win

import (
	yu_math "gogs.qqck.cn/s/tools/math"
	_ "syscall"
	_ "unsafe"
)

//go:linkname SyscallN syscall.SyscallN
func SyscallN(addr uintptr, args ...uintptr) (r1, r2, err uintptr)

type Code byte

const (
	Gbk Code = iota
	Unicode
)

type S struct {
	// Code
	//
	//	@Description: 要将字符串转换为哪种编码，转换后会自动在尾部补充 \x00 结束符
	//	 utf8 请直接传递 string，无需此高级类型，utf8 请自行决定是否在尾部补充 \x00 结束符
	Code Code

	// Utf8
	//
	//	@Description: 欲转换的 utf8 字符串
	Utf8 string
}

type Address uintptr

func (t Address) CallInt(args ...any) int {
	j_i, _, _ := t.Call(args...)
	return int(j_i)
}

func (t Address) CallInt32(args ...any) int32 {
	j_i, _, _ := t.Call(args...)
	return int32(j_i)
}

func (t Address) CallUint(args ...any) uint {
	j_i, _, _ := t.Call(args...)
	return uint(j_i)
}

func (t Address) CallUint32(args ...any) uint32 {
	j_i, _, _ := t.Call(args...)
	return uint32(j_i)
}

func (t Address) CallBool(args ...any) bool {
	j_i, _, _ := t.Call(args...)
	return j_i == 1
}

func (t Address) CallUintptr(args ...any) uintptr {
	j_i, _, _ := t.Call(args...)
	return j_i
}

func (t Address) CallGbkToUtf8(args ...any) string {
	j_str, _, _ := t.Call(args...)
	if j_str == 0 {
		return ""
	}

	j_unicode_len, _, _ := MultiByteToWideChar.Call(936, 0, j_str, uint(yu_math.MaxUint), 0, 0)
	if j_unicode_len < 1 {
		return ""
	}
	j_unicode_len *= 2
	j_unicode := make([]byte, j_unicode_len+2) // 结尾 {0,0}
	MultiByteToWideChar.Call(936, 0, j_str, uint(yu_math.MaxUint), j_unicode, j_unicode_len)

	j_utf8_size, _, _ := WideCharToMultiByte.Call(65001, 0, j_unicode, uint(yu_math.MaxUint), 0, 0, 0, 0)
	j_utf8_size -= 1
	if j_utf8_size < 1 {
		return ""
	}
	j_utf8 := make([]byte, j_utf8_size)
	WideCharToMultiByte.Call(65001, 0, j_unicode, uint(yu_math.MaxUint), j_utf8, j_utf8_size, 0, 0)

	return string(j_utf8)
}

func (t Address) CallUnicodeToUtf8(args ...any) string {
	j_ptr, _, _ := t.Call(args...)
	if j_ptr == 0 {
		return ""
	}

	j_utf8_size, _, _ := WideCharToMultiByte.Call(65001, 0, j_ptr, uint(yu_math.MaxUint), 0, 0, 0, 0)
	j_utf8_size -= 1
	if j_utf8_size < 1 {
		return ""
	}
	j_utf8 := make([]byte, j_utf8_size)
	WideCharToMultiByte.Call(65001, 0, j_ptr, uint(yu_math.MaxUint), j_utf8, j_utf8_size, 0, 0)

	return string(j_utf8)
}

type Module uintptr

func LoadLibrary(path string) Module {
	return Module(LoadLibraryW.CallUintptr(S{Unicode, path}))
}

func (t Module) GetProcAddress(name string) Address {
	return Address(GetProcAddress.CallUintptr(uintptr(t), name+"\x00"))
}
