package org.kne.cloud.network.tun;
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.time.Duration;

/**
 * Windows WaitForSingleObject 函数封装
 * 专用于等待 WintunGetReadWaitEvent 返回的事件句柄
 */
public class WindowsWaitHandle {
    
    // 常量定义
    public static final long INFINITE = 0xFFFFFFFFL;  // 无限等待
    public static final long WAIT_OBJECT_0 = 0x00000000L;  // 事件已发出信号
    public static final long WAIT_TIMEOUT = 0x00000102L;   // 超时
    public static final long WAIT_FAILED = 0xFFFFFFFFL;    // 失败
    
    // 内存布局
    public static final AddressLayout POINTER = ValueLayout.ADDRESS;
    public static final ValueLayout.OfInt DWORD = ValueLayout.JAVA_INT;
    public static final ValueLayout.OfLong DWORD64 = ValueLayout.JAVA_LONG;
    
    // Native库加载
    private static final SymbolLookup LOOKUP;
    private static final Linker LINKER = Linker.nativeLinker();
    
    // 方法句柄
    private static final MethodHandle WAIT_FOR_SINGLE_OBJECT;
    
    static {
        try {
            // 加载 kernel32.dll
            System.loadLibrary("kernel32");
            LOOKUP = SymbolLookup.loaderLookup();
            
            // 定义函数描述符
            // DWORD WINAPI WaitForSingleObject(
            //   _In_ HANDLE hHandle,
            //   _In_ DWORD  dwMilliseconds
            // );
            FunctionDescriptor waitForSingleObjectDesc = FunctionDescriptor.of(
                DWORD,      // 返回值: DWORD
                POINTER,    // hHandle: HANDLE
                DWORD       // dwMilliseconds: DWORD
            );
            
            // 获取函数句柄
            WAIT_FOR_SINGLE_OBJECT = LINKER.downcallHandle(
                LOOKUP.find("WaitForSingleObject").orElseThrow(),
                waitForSingleObjectDesc
            );
            
        } catch (Throwable e) {
            throw new RuntimeException("Failed to initialize WindowsWaitHandle", e);
        }
    }
    
    /**
     * 等待单个对象（事件句柄）
     * 
     * @param handle 要等待的事件句柄（MemorySegment）
     * @param timeoutMillis 超时时间（毫秒），0表示立即返回，INFINITE表示无限等待
     * @return 等待结果：WAIT_OBJECT_0, WAIT_TIMEOUT, 或 WAIT_FAILED
     */
    public static long waitForSingleObject(MemorySegment handle, long timeoutMillis) {
        try {
            int timeout;
            if (timeoutMillis == INFINITE) {
                timeout = (int)INFINITE;  // 0xFFFFFFFF
            } else if (timeoutMillis > 0xFFFFFFFFL) {
                timeout = (int)INFINITE;  // 超过DWORD最大值，使用INFINITE
            } else {
                timeout = (int)timeoutMillis;
            }
            
            int result = (int) WAIT_FOR_SINGLE_OBJECT.invokeExact(
                handle,
                timeout
            );
            
            return result & 0xFFFFFFFFL;  // 无符号转换
        } catch (Throwable e) {
            throw new RuntimeException("Error calling WaitForSingleObject", e);
        }
    }
    
    /**
     * 等待事件（使用Duration）
     */
    public static long waitForSingleObject(MemorySegment handle, Duration timeout) {
        if (timeout == null) {
            return waitForSingleObject(handle, INFINITE);
        }
        
        long millis = timeout.toMillis();
        if (millis <= 0) {
            return waitForSingleObject(handle, 0);  // 立即返回
        }
        
        return waitForSingleObject(handle, millis);
    }
    
    /**
     * 无限等待事件
     */
    public static long waitForSingleObjectInfinite(MemorySegment handle) {
        return waitForSingleObject(handle, INFINITE);
    }
    
    /**
     * 非阻塞检查事件（立即返回）
     */
    public static long waitForSingleObjectNoWait(MemorySegment handle) {
        return waitForSingleObject(handle, 0);
    }
    
    /**
     * 等待事件，带重试机制
     */
    public static boolean waitWithRetry(MemorySegment handle, int maxRetries, long timeoutPerRetry) {
        for (int i = 0; i < maxRetries; i++) {
            long result = waitForSingleObject(handle, timeoutPerRetry);
            
            if (result == WAIT_OBJECT_0) {
                return true;  // 事件已发出信号
            } else if (result == WAIT_TIMEOUT) {
                // 超时，继续重试
                continue;
            } else if (result == WAIT_FAILED) {
                // 失败，停止重试
                break;
            }
        }
        return false;
    }
    
    /**
     * 检查等待结果
     */
    public static boolean isWaitSuccess(long waitResult) {
        return waitResult == WAIT_OBJECT_0;
    }
    
    public static boolean isWaitTimeout(long waitResult) {
        return waitResult == WAIT_TIMEOUT;
    }
    
    public static boolean isWaitFailed(long waitResult) {
        return waitResult == WAIT_FAILED;
    }
    
    /**
     * 获取等待结果的描述
     */
    public static String getWaitResultDescription(long waitResult) {
        if (waitResult == WAIT_OBJECT_0) {
            return "Event signaled (WAIT_OBJECT_0)";
        } else if (waitResult == WAIT_TIMEOUT) {
            return "Timeout (WAIT_TIMEOUT)";
        } else if (waitResult == WAIT_FAILED) {
            return "Failed (WAIT_FAILED)";
        } else {
            return String.format("Unknown result: 0x%08X", waitResult);
        }
    }
}