import t, c
from stdint import *
from w32.win32base import *
from w32.win32process import CreateThread, GetExitCodeThread, GetCurrentThreadId, TlsAlloc, TlsFree, TlsGetValue, TlsSetValue
from w32.win32sync import WaitForSingleObject

# All lock classes are imported, and users can also import them as needed.
from lock import Lock
from event import Event
from condition import Condition
from rwlock import RWLock


class Thread:
    """Thread class, wraps Windows CreateThread.

    Thread callback signature: def thread_func(arg: t.CPtr) -> t.CPtr
    Note: Windows API limits the return value to DWORD (32-bit), so 64-bit pointers will be truncated.
    If you need to return a 64-bit result, pass it via the arg parameter struct.

    Usage:
        def worker(arg: t.CPtr) -> t.CPtr:
            # thread logic
            return NULL

        t: Thread = Thread(worker, arg_ptr)
        t.start()
        t.join()
    """
    handle: HANDLE
    thread_id: ULONG
    target: VOIDPTR
    arg: VOIDPTR
    started: BOOL

    def __init__(self, target: VOIDPTR, arg: VOIDPTR = NULL):
        self.handle = NULL
        self.thread_id = 0
        self.target = target
        self.arg = arg
        self.started = FALSE

    def start(self):
        if self.started:
            return
        self.handle = CreateThread(NULL, 0, self.target, self.arg, 0, c.Addr(self.thread_id))
        self.started = TRUE

    def join(self, timeout_ms: ULONG = INFINITE) -> BOOL:
        if not self.started:
            return FALSE
        result: ULONG = WaitForSingleObject(self.handle, timeout_ms)
        return result == WAIT_OBJECT_0

    def is_alive(self) -> BOOL:
        if not self.started:
            return FALSE
        result: ULONG = WaitForSingleObject(self.handle, 0)
        return result == WAIT_TIMEOUT

    def get_exit_code(self) -> ULONG:
        code: ULONG = 0
        GetExitCodeThread(self.handle, c.Addr(code))
        return code

    def close(self):
        if self.handle != NULL:
            CloseHandle(self.handle)
            self.handle = NULL


class local:
    """TLS (Thread Local Storage) encapsulation.

    Usage:
        tls: local = local()
        tls.set(value_ptr)
        val: t.CPtr = tls.get()
    """
    index: ULONG

    def __init__(self):
        self.index = TlsAlloc()

    def get(self) -> VOIDPTR:
        return TlsGetValue(self.index)

    def set(self, value: VOIDPTR) -> BOOL:
        return TlsSetValue(self.index, value)

    def free(self) -> BOOL:
        return TlsFree(self.index)


def get_current_thread_id() -> ULONG:
    """Get current thread ID"""
    return GetCurrentThreadId()


def sleep_ms(ms: ULONG):
    """Make the current thread sleep for a specified number of milliseconds"""
    Sleep(ms)
