#![deny(clippy::all)]
#![allow(non_snake_case)]

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename = "WMIMonitorID")]
#[napi_derive::napi(object)]
pub struct WmiMonitorID {
    pub WeekOfManufacture: u8,
    pub InstanceName: String,
    pub UserFriendlyNameLength: u16,
    pub UserFriendlyName: Vec<u16>,
    pub YearOfManufacture: u16,
    pub ManufacturerName: Vec<u16>,
    pub ProductCodeID: Vec<u16>,
    pub SerialNumberID: Vec<u16>,
    pub Active: bool,
}

impl WmiMonitorID {
    // Generic get Function to instantly convert the requested field and return as string
    pub fn get(&self, field: &str) -> String {
        match field {
            "WeekOfManufacture" => self.WeekOfManufacture.to_string(),
            "InstanceName" => self.InstanceName.clone(),
            "UserFriendlyNameLength" => self.UserFriendlyNameLength.to_string(),
            "UserFriendlyName" => WmiMonitorID::get_parsed_string(&self.UserFriendlyName),
            "YearOfManufacture" => self.YearOfManufacture.to_string(),
            "ManufacturerName" => WmiMonitorID::get_parsed_string(&self.ManufacturerName),
            "ProductCodeID" => WmiMonitorID::get_parsed_string(&self.ProductCodeID),
            "SerialNumberID" => WmiMonitorID::get_parsed_string(&self.SerialNumberID),
            "Active" => self.Active.to_string(),
            _ => "Unknown".to_string()
        }
    }

    pub fn get_parsed_string(text: &[u16]) -> String {
        text.iter()
            .map(|&x| x as u8 as char)
            .filter(|&x| x != '\0')
            .collect()
    }
}

#[cfg(target_os = "windows")]
pub mod displays {
    use wmi::*;
    use crate::DefaultResult;
    use crate::displays::WmiMonitorID;

    impl WmiMonitorID {
        pub  fn get_displays(connection: &WmiConnection) -> DefaultResult<Vec<WmiMonitorID>> {
            let displays: Vec<WmiMonitorID> = connection.wmi_con.query()?;
            Ok(displays)
        }
    }

    pub struct WmiConnection {
        pub wmi_con: WMIConnection,
    }

    impl WmiConnection {
        pub fn new() -> DefaultResult<WmiConnection> {
            Ok(WmiConnection {
                wmi_con: WMIConnection::with_namespace_path("root\\wmi", COMLibrary::new_without_init()?)?,
            })
        }
    }

    #[napi]
    pub fn get_displays() -> Vec<WmiMonitorID> {
        let wmi_con = match WmiConnection::new() {
            Ok(con) => {con},
            Err(e) => {
                eprintln!("WMI Connection: {e:?}");
                return vec![];
            }
        };

        let dd = match WmiMonitorID::get_displays(&wmi_con) {
            Ok(displays) => displays.clone().to_owned(),
            Err(e) => {
                eprintln!("Get Displays: {e:?}");
                vec![]
            }
        };

        dd
    }
}

#[cfg(target_os = "macos")]
pub mod displays {
    use crate::displays::WmiMonitorID;
    #[napi]
    pub fn get_displays() -> Vec<WmiMonitorID> {
        // Always return an empty list on non-Windows platforms
        vec![]
    }
}