use std::error::Error;

use rog_platform::hid_raw::HidRaw;

pub fn main() -> Result<(), Box<dyn Error>> {
    let mut usb_node = None;
    match HidRaw::new("1abe") {
        Ok(node) => {
            let id = node.prod_id().to_owned();
            usb_node = Some(node);
            println!("Looked for keyboard controller 0x{}: Found", id);
        }
        Err(err) => println!("Looked for keyboard controller: {err}"),
    }

    if usb_node.is_none() {
        return Err("RogError::NoAuraKeyboard".into());
    }

    let node = usb_node.unwrap();

    let mut packet: [u8; 64] = [
        0x5a, 0xd1, 0x0d, 0x0e, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ];

    let x_stable = 2107;
    let x_min = 815;
    let x_max = 3399;

    let y_stable = 2223;
    let y_min = 1020;
    let y_max = 3427;

    let bb = |n: u32| ((n & 0xff00) >> 8) as u8;
    let lb = |n: u32| (n & 0xff) as u8;

    let checksum = |bytes: &[u8]| {
        let total = bytes.iter().fold(0, |a, n| a + (*n) as u32);
        total as u8
    };

    packet[6] = bb(y_stable);
    packet[7] = lb(y_stable);
    packet[8] = bb(y_min);
    packet[9] = lb(y_min);
    packet[10] = bb(y_max);
    packet[11] = lb(y_max);
    packet[12] = bb(x_stable);
    packet[13] = lb(x_stable);
    packet[14] = bb(x_min);
    packet[15] = lb(x_min);
    packet[16] = bb(x_max);
    packet[17] = lb(x_max);
    packet[18] = checksum(&packet[6..=17]);

    for n in &packet[6..=17] {
        print!("{:0x},", n);
    }
    println!();
    println!("Checksum: {:0x}", packet[18]);

    node.write_bytes(&packet)?;

    let reset = false;
    if reset {
        let packet: [u8; 64] = [
            0x5a, 0xd1, 0x0d, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        ];
        node.write_bytes(&packet)?;
    }
    // Apply
    let packet: [u8; 64] = [
        0x5a, 0xd1, 0x0d, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ];
    node.write_bytes(&packet)?;

    Ok(())
}
