#[cfg(target_os = "linux")]
pub mod linux {}
use crate::parse::AutoParse;
#[cfg(target_os = "linux")]
pub use linux::*;
use serde::{Deserialize, Serialize};
use std::{ffi::*, ptr};

/// Ui数据便于全局处理
#[repr(C)]
#[derive(Debug)]
pub struct UiData {
    hwnd: HWND,
}
impl Default for UiData {
    fn default() -> Self {
        Self {
            hwnd: ptr::null_mut(),
        }
    }
}
unsafe impl Send for UiData {}
unsafe impl Sync for UiData {}
/// UI配置
impl UiData {
    /// 创建UI
    pub unsafe extern "system" fn create_ui(
        &mut self,
        ui_conf: CUiConfig,
        ui_callback: UiCallback,
    ) {
        let hwnd = create_ui(ui_conf, ui_callback);
        self.set_hwnd(hwnd)
    }
    /// 销毁UI
    pub unsafe extern "system" fn destroy_ui(&mut self) {
        if destroy_ui(self.hwnd) {
            self.set_hwnd(ptr::null_mut())
        }
    }
}
// 基础配置
impl UiData {
    /// 设置hwnd句柄
    pub fn set_hwnd(&mut self, hwnd: HWND) {
        self.hwnd = hwnd
    }
    /// 获取hwnd句柄
    pub fn get_hwnd(&self) -> HWND {
        self.hwnd
    }
}

/// UI配置
#[derive(Debug, Deserialize, Serialize, Default, Clone, e_macros::Json)]
#[serde(rename_all = "camelCase")]
pub struct UiConfig {
    /// 标题
    pub title: String,
    /// class名称
    pub class_name: String,
    /// x 坐标
    pub x: i32,
    /// y 坐标
    pub y: i32,
    /// 窗口宽度
    pub width: i32,
    /// 窗口高度
    pub height: i32,
}
/// Ui配置
///
/// 默认值:
///```
/// CUiConfig {
///   title: "heg-window".to_string(),
///   class_name: "heg-window".to_string(),
///   x: 0,
///   y: 0,
///   width: 300,
///   height: 300,
///   hwnd_parent: std::ptr::null_mut(),
/// }
/// ```
#[repr(C)]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CUiConfig {
    /// 标题
    #[serde(with = "crate::parse::c_str_pointer_serializer")]
    pub title: *const c_char,
    /// class名称
    #[serde(with = "crate::parse::c_str_pointer_serializer")]
    pub class_name: *const c_char,
    /// x 坐标
    pub x: c_int,
    /// y 坐标
    pub y: c_int,
    /// 窗口宽度
    pub width: c_int,
    /// 窗口高度
    pub height: c_int,
}

impl Default for CUiConfig {
    fn default() -> Self {
        CUiConfig {
            title: "heg-window".to_c_char(),
            class_name: "heg-window".to_c_char(),
            x: 0,
            y: 0,
            width: 300,
            height: 300,
        }
    }
}

/// windows平台
#[cfg(target_os = "windows")]
pub mod win {
    use super::CUiConfig;
    use std::ffi::{c_int, CStr};
    use std::ptr;
    pub use winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM};
    pub use winapi::shared::windef::{HWND, RECT};
    use winapi::um::winnt::LPCSTR;
    pub use winapi::um::winuser::WM_DESTROY;
    use winapi::um::winuser::{
        CloseWindow, CreateWindowExW, DefWindowProcW, FindWindowA, RegisterClassW, SendMessageA,
        WM_CLOSE, WNDCLASSW, WS_OVERLAPPEDWINDOW, WS_VISIBLE,
    };
    /// 回调函数类型
    pub type UiCallback = winapi::um::winuser::WNDPROC;
    /// 退出
    pub fn exit_ui(exit_code: c_int) {
        unsafe { winapi::um::winuser::PostQuitMessage(exit_code) };
    }
    /// 缩小窗口
    pub unsafe extern "system" fn close_ui(hwnd: HWND) -> bool {
        CloseWindow(hwnd) > 0
    }
    /// 关闭窗口
    pub unsafe extern "system" fn destroy_ui(hwnd: HWND) -> bool {
        println!("destory ");
        // 销毁窗口
        // DestroyWindow(hwnd) > 0
        let res = SendMessageA(hwnd, WM_CLOSE, 0, 0);
        res == 0
    }
    /// #查询窗口句柄
    ///
    /// 根据class名 或标题名查询
    /// ptr::null_mut()则忽略
    pub unsafe extern "system" fn find_ui_hwnd(class_name: LPCSTR, title_name: LPCSTR) -> HWND {
        FindWindowA(class_name, title_name)
    }
    /// 渲染窗口
    pub unsafe fn draw_ui(hwnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
        DefWindowProcW(hwnd, msg, w_param, l_param)
    }
    /// 创建窗口
    pub unsafe extern "system" fn create_ui(ui_conf: CUiConfig, ui_callback: UiCallback) -> HWND {
        let class_name = format!("{}\0", CStr::from_ptr(ui_conf.class_name).to_string_lossy())
            .encode_utf16()
            .collect::<Vec<u16>>();
        let window_name = format!("{}\0", CStr::from_ptr(ui_conf.title).to_string_lossy())
            .encode_utf16()
            .collect::<Vec<u16>>();
        let wnd_class = WNDCLASSW {
            style: 0,
            lpfnWndProc: ui_callback,
            hInstance: ptr::null_mut(),
            lpszClassName: class_name.as_ptr(),
            cbClsExtra: 0,
            cbWndExtra: 0,
            hIcon: ptr::null_mut(),
            hCursor: ptr::null_mut(),
            hbrBackground: ptr::null_mut(),
            lpszMenuName: ptr::null_mut(),
        };

        unsafe { RegisterClassW(&wnd_class) };

        unsafe {
            CreateWindowExW(
                0,
                class_name.as_ptr(),
                window_name.as_ptr(),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                ui_conf.x,
                ui_conf.y,
                ui_conf.width,
                ui_conf.height,
                ptr::null_mut(),
                ptr::null_mut(),
                ptr::null_mut(),
                ptr::null_mut(),
            )
        }
    }
    /// Window procedure callback
    pub unsafe extern "system" fn ui_callback(
        hwnd: HWND,
        msg: UINT,
        w_param: WPARAM,
        l_param: LPARAM,
    ) -> LRESULT {
        match msg {
            WM_DESTROY => 0,
            _ => draw_ui(hwnd, msg, w_param, l_param),
        }
    }
}
#[cfg(target_os = "windows")]
pub use win::*;
