use json::{object, JsonValue};

use crate::mac::Mac;
#[cfg(target_os = "macos")]
pub mod mac;
#[cfg(target_os = "windows")]
pub mod win;
pub fn run<F>(factory: F)
where
    F: Fn() -> Box<dyn Handler>,
{
    #[cfg(target_os = "windows")]
    win::Win::new().run(factory);
    #[cfg(target_os = "macos")]
    Mac::new().run(factory)
}
pub fn connect<F>(id: String, factory: F)
where
    F: Fn() -> Box<dyn Handler>,
{
    #[cfg(target_os = "windows")]
    Win::new().connect(id, factory);
    #[cfg(target_os = "macos")]
    Mac::new().connect(id, factory)
}
pub trait Handler {
    fn on_discover(&mut self, device: Device);
    fn on_data(&mut self, id: String, value: JsonValue);
    fn on_is_close(&mut self, id: String) -> bool;
    fn on_disconnected(&mut self, id: String, error: String);
    fn on_connect(&mut self, id: String);
}

/// 蓝牙HID设备
#[derive(Clone)]
pub struct Device {
    /// 设备唯一id
    pub id: String,
    pub vid: String,
    pub pid: String,
    pub types: Types,
    /// 制造商
    pub manufacturer: String,
    /// 设备名称
    pub name: String,
    /// 计数
    pub count: u8,
    /// 值
    pub value: JsonValue,
}
impl Device {
    pub fn json(&mut self) -> JsonValue {
        object! {
            "id": self.id.clone(),
            "name": self.name.clone(),
            "vid": self.vid.clone(),
            "pid": self.pid.clone(),
            "manufacturer": self.manufacturer.clone(),
            "types": self.types.str(),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Types {
    /// 键盘
    Keyboard,
    /// 鼠标
    Mouse,
    None,
}
impl Types {
    fn str(&mut self) -> &'static str {
        match self {
            Types::Keyboard => "keyboard",
            Types::Mouse => "mouse",
            Types::None => "",
        }
    }
    #[allow(dead_code)]
    fn from(name: &str) -> Self {
        match name {
            "keyboard" => Types::Keyboard,
            "mouse" => Types::Mouse,
            _ => Types::None,
        }
    }
}
