//! NXUI is a cross-platform GUI toolkit.

pub mod demo;
pub mod directory_chooser;
pub mod file_chooser;
pub mod graphic;
pub mod io;
pub mod messagebox;
pub mod natives_and_messaging;
pub mod nxui;
pub mod util;
pub mod widget;
pub mod window;
pub mod cli;

#[macro_use]
extern crate log;
extern crate env_logger as logger;

use std::env;
use std::iter::once;

#[cfg(windows)]
#[no_mangle] pub extern "C" fn initialize() -> bool {
    env::set_var("RUST_LOG", "info");
    logger::init();
    info!("OS: Windows");
    info!(
        "Running directory: {}",
        std::env::current_dir().unwrap().to_str().unwrap()
    );
    info!("NXUI is being initialized.");
    enable_visual_style();
    info!("Visual Style applied.");
    true
}

#[cfg(macos)]
#[no_mangle] pub extern "C" fn initialize() -> bool{
    env::set_var("RUST_LOG", "info");
    logger::init();
    info!("OS: MacOS");
    info!(
        "Running directory: {}",
        std::env::current_dir().unwrap().to_str().unwrap()
    );
    true
}

#[cfg(unix)]
#[no_mangle] pub extern "C" fn initialize() -> bool {
    env::set_var("RUST_LOG", "info");
    logger::init();
    info!("OS: Unix");
    info!(
        "Running directory: {}",
        std::env::current_dir().unwrap().to_str().unwrap()
    );
    info!("NXUI is being initialized.");
    gtk::init().expect("Failed to initialize GTK.");
    true
}

/// Enabling Visual Style
#[cfg(windows)]
fn enable_visual_style() {
    use std::{mem, ptr};
    use winapi::shared::basetsd::ULONG_PTR;
    use winapi::shared::minwindef::{DWORD, ULONG};
    use winapi::um::sysinfoapi::GetSystemDirectoryW;
    use winapi::um::winbase::{ActivateActCtx, CreateActCtxW, ACTCTXW};
    use windows_sys::Win32::Foundation::MAX_PATH;

    const ACTCTX_FLAG_RESOURCE_NAME_VALID: DWORD = 0x008;
    const ACTCTX_FLAG_SET_PROCESS_DEFAULT: DWORD = 0x010;
    const ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID: DWORD = 0x004;

    let mut sys_dir: Vec<u16> = Vec::with_capacity(MAX_PATH as usize);
    unsafe {
        sys_dir.set_len(MAX_PATH as usize);
        GetSystemDirectoryW(sys_dir.as_mut_ptr(), MAX_PATH as u32);
    }

    let mut source = "shell32.dll"
        .encode_utf16()
        .chain(once(0))
        .collect::<Vec<u16>>();

    let mut activation_cookie: ULONG_PTR = 0;
    let mut act_ctx = ACTCTXW {
        cbSize: mem::size_of::<ACTCTXW> as ULONG,
        dwFlags: ACTCTX_FLAG_RESOURCE_NAME_VALID
            | ACTCTX_FLAG_SET_PROCESS_DEFAULT
            | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
        lpSource: source.as_mut_ptr().cast(),
        wProcessorArchitecture: 0,
        wLangId: 0,
        lpAssemblyDirectory: sys_dir.as_mut_ptr(),
        lpResourceName: unsafe { mem::transmute(124usize) },
        lpApplicationName: ptr::null_mut(),
        hModule: ptr::null_mut(),
    };

    unsafe {
        let handle = CreateActCtxW(&mut act_ctx);
        ActivateActCtx(handle, &mut activation_cookie);
    }
}
