use std::thread;
use std::time::Duration;
use hidapi::{HidApi};
use json::JsonValue;
use crate::{Device, Handler, Types};

#[derive(Clone)]
pub struct Mac {}
impl Default for Mac {
    fn default() -> Self {
        Self::new()
    }
}

impl Mac {
    pub fn new() -> Self {
        Self {}
    }
    /// 运行
    pub fn run<F>(&mut self, factory: F)
    where
        F: Fn() -> Box<dyn Handler>,
    {
        loop {
            let hidapi = match HidApi::new() {
                Ok(e) => e,
                Err(_) => {
                    continue;
                }
            };
            for device in hidapi.device_list() {
                let usage = device.usage();
                let usage_page = device.usage_page();

                if usage != 6 || usage_page != 1 {
                    continue;
                }


                let uid = if device.release_number() == 0 {
                    let path = device.path().to_str().unwrap().to_string();
                    let re = path.trim().trim_start_matches("DevSrvsID:").parse::<u64>().unwrap();
                    u64_to_mac(re)
                } else {
                    device.serial_number().unwrap().to_string()
                };


                let r = Device {
                    id: uid,
                    vid: device.vendor_id().to_string(),
                    pid: device.product_id().to_string(),
                    types: Types::Keyboard,
                    manufacturer: device.manufacturer_string().unwrap().trim().to_string(),
                    name: device.product_string().unwrap().trim().to_string(),
                    value: JsonValue::from("".to_string()),
                    count: 0,
                };
                factory().on_discover(r);
            }
            thread::sleep(Duration::from_secs(1));
        }
    }
    pub fn connect<F>(&mut self, id: String, factory: F)
    where
        F: Fn() -> Box<dyn Handler>,
    {
        let hidapi = match HidApi::new() {
            Ok(e) => e,
            Err(e) => {
                return factory().on_disconnected(id, e.to_string());
            }
        };

        let device = hidapi.device_list().find(|device| {
            let uid = if device.release_number() == 0 {
                let path = device.path().to_str().unwrap().to_string();
                let re = path.trim().trim_start_matches("DevSrvsID:").parse::<u64>().unwrap();
                u64_to_mac(re)
            } else {
                device.serial_number().unwrap().to_string()
            };
            uid == id
        });

        let device_info = match device {
            Some(device) => device,
            None => {
                return factory().on_disconnected(id, "未找到设备".to_string());
            }
        };

        let device = match device_info.open_device(&hidapi) {
            Ok(e) => e,
            Err(e) => return factory().on_disconnected(id, e.to_string())
        };
        factory().on_connect(id.clone());
        let mut value = "".to_string();
        loop {
            if factory().on_is_close(id.clone()) {
                factory().on_disconnected(id.clone(), "主动断开连接".to_string());
                break;
            }
            let mut buf = [0u8; 64];
            match device.read_timeout(&mut buf, 1000) {
                Ok(n) => {
                    let data = &buf[..n];
                    if data.is_empty() {
                        continue;
                    }
                    if data[4] != 0 {
                        continue;
                    }
                    value = format!("{value}{}", keycode_to_digit(data[3]));
                    match value.find("\n") {
                        None => {}
                        Some(e) => {
                            value = value[..e].to_string();
                            factory().on_data(id.clone(), value.into());
                            value = "".to_string();
                        }
                    }
                }
                Err(e) => {
                    factory().on_disconnected(id.clone(), format!("设备连接失败: {}",e));
                    break;
                }
            }
        }
    }
}

fn keycode_to_digit(keycode: u8) -> &'static str {
    match keycode {
        88 | 40 => "\n",
        86 | 45 => "-",
        87 | 46 => "+",
        89 | 30 => "1",
        90 | 31 => "2",
        91 | 32 => "3",
        92 | 33 => "4",
        93 | 34 => "5",
        94 | 35 => "6",
        95 | 36 => "7",
        96 | 37 => "8",
        97 | 38 => "9",
        98 | 39 => "0",
        99 | 55 => ".",
        _ => "",
    }
}

fn u64_to_mac(val: u64) -> String {
    let bytes = val.to_be_bytes(); // 转成大端 8 字节
    let mac_bytes = &bytes[2..];   // MAC 只有后 6 字节
    mac_bytes.iter().map(|b| format!("{:02X}", b)).collect::<Vec<_>>().join(":")
}
