#import "Windows";

// DLL imports
user32   :: #system_library "user32";
gdi32    :: #system_library "gdi32";
shell32  :: #system_library "shell32";

// Structs
NOTIFYICONDATAW :: struct {
    cbSize: u32;
    hWnd: HWND;
    uID: u32;
    uFlags: u32;
    uCallbackMessage: u32;
    hIcon: HICON;
    szTip: [128] u16;
    dwState: u32;
    dwStateMask: u32;
    szInfo: [256] u16;
    uTimeoutOrVersion: u32;
    szInfoTitle: [64] u16;
    dwInfoFlags: u32;
    guidItem: GUID;
    hBalloonIcon: HICON;
}

// Win32 constants
DEFAULT_GUI_FONT  :: 17;
COLOR_WINDOW      :: 5;
SS_LEFT           :: 0x00000000;
ES_AUTOHSCROLL    :: 0x0080;
BS_DEFPUSHBUTTON  :: 0x00000001;
BS_PUSHBUTTON     :: 0x00000000;
GWLP_USERDATA     :: -21;
WM_SETFONT        :: 0x0030;

STARTF_USESHOWWINDOW : s32 : 0x00000001;

TPM_LEFTALIGN     : u32 : 0x00000000;
TPM_RIGHTBUTTON   : u32 : 0x00000002;
TPM_RETURNCMD     : u32 : 0x00000100;

MF_STRING         : u32 : 0x00000000;
MF_GRAYED         : u32 : 0x00000001;
MF_DISABLED       : u32 : 0x00000002;
MF_SEPARATOR      : u32 : 0x00000800;
MF_CHECKED        : u32 : 0x00000008;

NIM_ADD           : u32 : 0x00000000;
NIM_MODIFY        : u32 : 0x00000001;
NIM_DELETE        : u32 : 0x00000002;

NIF_MESSAGE       : u32 : 0x00000001;
NIF_ICON          : u32 : 0x00000002;
NIF_TIP           : u32 : 0x00000004;

// Functions
IsDialogMessageW :: (hDlg: HWND, lpMsg: *MSG) -> BOOL #foreign user32;
GetWindowLongPtrW :: (hWnd: HWND, nIndex: s32) -> s64 #foreign user32;
Shell_NotifyIconW :: (dwMessage: u32, lpData: *NOTIFYICONDATAW) -> BOOL #foreign shell32;

CreatePopupMenu :: () -> HMENU #foreign user32;
DestroyMenu :: (hMenu: HMENU) -> BOOL #foreign user32;
AppendMenuW :: (hMenu: HMENU, uFlags: u32, uIDNewItem: s64, lpNewItem: LPCWSTR) -> BOOL #foreign user32;
TrackPopupMenu :: (hMenu: HMENU, uFlags: u32, x: s32, y: s32, nReserved: s32, hWnd: HWND, prcRect: *RECT) -> BOOL #foreign user32;
SetForegroundWindow :: (hWnd: HWND) -> BOOL #foreign user32;
EnableWindow :: (hWnd: HWND, bEnable: BOOL) -> BOOL #foreign user32;
PostMessageW :: (hWnd: HWND, Msg: u32, wParam: WPARAM, lParam: LPARAM) -> BOOL #foreign user32;

// Custom message IDs
WM_USER             :: 0x0400;
WM_TRAY_CALLBACK    :: WM_USER + 1;
WM_RESTART_SINGBOX  :: WM_USER + 2;

// Context menu command IDs
CMD_STATUS          :: 1001;
CMD_START_STOP      :: 1002;
CMD_SET_URL         :: 1003;
CMD_UPDATE_NOW      :: 1004;
CMD_EXIT            :: 1005;
CMD_MODE_PROXY      :: 1006;
CMD_MODE_SYS_PROXY  :: 1007;

// Boolean constants
FALSE               :: 0;
TRUE                :: 1;

// CREATESTRUCTW definition
CREATESTRUCTW :: struct {
    lpCreateParams: *void;
    hInstance: HINSTANCE;
    hMenu: HMENU;
    hwndParent: HWND;
    cy: s32;
    cx: s32;
    y: s32;
    x: s32;
    style: s32;
    lpszName: LPCWSTR;
    lpszClass: LPCWSTR;
    dwExStyle: DWORD;
}

kernel32 :: #system_library "kernel32";

LONG_PTR :: s64;
UINT_PTR :: u64;

// Window and Message Functions
GetMessageW :: (lpMsg: *MSG, hWnd: HWND, wMsgFilterMin: u32, wMsgFilterMax: u32) -> BOOL #foreign user32;

SetTimer :: (hWnd: HWND, nIDEvent: UINT_PTR, uElapse: u32, lpTimerFunc: *void) -> UINT_PTR #foreign user32;
KillTimer :: (hWnd: HWND, uIDEvent: UINT_PTR) -> BOOL #foreign user32;



GetWindowTextW :: (hWnd: HWND, lpString: *u16, nMaxCount: s32) -> s32 #foreign user32;
GetWindowTextLengthW :: (hWnd: HWND) -> s32 #foreign user32;


SendMessageW :: (hWnd: HWND, Msg: u32, wParam: WPARAM, lParam: LPARAM) -> LRESULT #foreign user32;
SetEvent :: (hEvent: HANDLE) -> BOOL #foreign kernel32;
SetFocus :: (hWnd: HWND) -> HWND #foreign user32;

LOWORD :: (val: WPARAM) -> u16 {
    return cast(u16) (val & 0xffff);
}

HIWORD :: (val: WPARAM) -> u16 {
    return cast(u16) ((val >> 16) & 0xffff);
}

PostThreadMessageW :: (idThread: DWORD, Msg: u32, wParam: WPARAM, lParam: LPARAM) -> BOOL #foreign user32;

advapi32 :: #system_library "advapi32";
wininet  :: #system_library "wininet";

LSTATUS :: s32;
REGSAM :: u32;

HKEY_CURRENT_USER :: cast(HKEY) 0x80000001;

KEY_WRITE     :: 0x20006;

INTERNET_OPTION_SETTINGS_CHANGED :: 39;
INTERNET_OPTION_REFRESH          :: 37;

RegOpenKeyExW :: (hKey: HKEY, lpSubKey: LPCWSTR, ulOptions: DWORD, samDesired: REGSAM, phkResult: *HKEY) -> LSTATUS #foreign advapi32;
RegSetValueExW :: (hKey: HKEY, lpValueName: LPCWSTR, Reserved: DWORD, dwType: DWORD, lpData: *u8, cbData: DWORD) -> LSTATUS #foreign advapi32;
RegCloseKey :: (hKey: HKEY) -> LSTATUS #foreign advapi32;

InternetSetOptionW :: (hInternet: HANDLE, dwOption: DWORD, lpBuffer: *void, dwBufferLength: DWORD) -> BOOL #foreign wininet;

wcslen :: (str: *u16) -> int {
    len := 0;
    while str[len] != 0 {
        len += 1;
    }
    return len;
}

set_windows_system_proxy :: (enable: bool, server: string) -> bool {
    hKey: HKEY;
    subkey := utf8_to_wide("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
    
    status := RegOpenKeyExW(HKEY_CURRENT_USER, subkey, 0, KEY_WRITE, *hKey);
    if status != 0 {
        return false;
    }
    defer RegCloseKey(hKey);

    enable_val: u32 = ifx enable then cast(u32) 1 else cast(u32) 0;
    status = RegSetValueExW(hKey, utf8_to_wide("ProxyEnable"), 0, REG_DWORD, cast(*u8) *enable_val, size_of(u32));
    if status != 0 return false;

    if enable {
        wide_server := utf8_to_wide(server);
        server_len_bytes := cast(u32) ((wcslen(wide_server) + 1) * 2);
        status = RegSetValueExW(hKey, utf8_to_wide("ProxyServer"), 0, REG_SZ, cast(*u8) wide_server, server_len_bytes);
        if status != 0 return false;
    }

    InternetSetOptionW(null, INTERNET_OPTION_SETTINGS_CHANGED, null, 0);
    InternetSetOptionW(null, INTERNET_OPTION_REFRESH, null, 0);

    return true;
}



