//! Global WINGs configuration.
//!
//! Use [`Configuration::global`] to get a snapshot of current configuration
//! settings.
//!
//! ## Rust rewrite notes
//!
//! This accesses a global that is defined in C code. Once more of WINGs is
//! migrated to Rust, we should use a different approach that is more
//! Rust-friendly. Threading a configuration object down the stack is a likely
//! way to go.

use crate::WINGsP::_WINGsConfiguration;

use std::{ffi::CStr, ptr::NonNull};

unsafe extern "C" {
    static WINGsConfiguration: _WINGsConfiguration;
}

#[derive(Clone, Copy, Debug)]
pub struct Configuration {
    pub system_font: &'static CStr,
    pub bold_system_font: &'static CStr,
    pub default_font_size: u16,
    pub antialiased_text: bool,
    pub floppy_path: &'static CStr,
    pub double_click_delay: u32,
    pub mouse_wheel_up: u32,
    pub mouse_wheel_down: u32,
}

impl Configuration {
    /// Returns the current WINGs configuration. Returns `None` if the
    /// configuration appears not to have been loaded.
    ///
    /// This should only be called after `W_ReadConfigurations` is called
    /// (presumably when initializing WINGs in C code), but it should be safe to
    /// call it at any time. (It may just contain nonsense values.)
    ///
    /// ## Rust rewrite notes
    ///
    /// We should migrate away from a static global and thread a configuration
    /// object in some other way.
    pub fn global() -> Option<Self> {
        let c = unsafe { &WINGsConfiguration };
        let system_font = unsafe { CStr::from_ptr(NonNull::new(c.systemFont)?.as_ptr()) };
        let bold_system_font = unsafe { CStr::from_ptr(NonNull::new(c.boldSystemFont)?.as_ptr()) };
        let default_font_size = u16::try_from(c.defaultFontSize).ok()?;
        let antialiased_text = c.antialiasedText != 0;
        let floppy_path = unsafe { CStr::from_ptr(NonNull::new(c.floppyPath)?.as_ptr()) };
        let double_click_delay = u32::try_from(c.doubleClickDelay).ok()?;
        let mouse_wheel_up = u32::try_from(c.mouseWheelUp).ok()?;
        let mouse_wheel_down = u32::try_from(c.mouseWheelDown).ok()?;
        Some(Configuration {
            system_font,
            bold_system_font,
            default_font_size,
            antialiased_text,
            floppy_path,
            double_click_delay,
            mouse_wheel_up,
            mouse_wheel_down,
        })
    }
}
