use {
    crate::{
        arch::hardware_random_u64,
        holeybytes::{kernel_services::block_read, Vm},
        ipc::{buffer::IpcBuffer, protocol::Protocol},
        kmain::IPC_BUFFERS,
    },
    hashbrown::HashMap,
    log::{info, trace},
    spin::{lazy::Lazy, Mutex},
};
pub struct Services<'a>(HashMap<u64, Protocol<'a>>);
pub static SERVICES: Lazy<Mutex<Services>> = Lazy::new(|| {
    let mut dt = Services(HashMap::new());
    dt.0.insert(0, Protocol::void());
    Mutex::new(dt)
});
#[derive(Debug)]
pub enum ServiceError {
    InvalidFormat,
}
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
    let msg_vec = block_read(mem_addr, length);
    let sds_event_type: ServiceEventType = msg_vec[0].into();
    let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
    let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
    let string_vec = block_read(strptr, strlen);
    let string = core::str::from_utf8(string_vec).expect("Our bytes should be valid utf8");

    use ServiceEventType::*;
    match sds_event_type {
        CreateService => {
            let ret = sds_create_service(string);
            vm.registers[1] = hbvm::value::Value(ret as u64);
        }
        DeleteService => todo!(),
        SearchServices => {
            let ret = sds_search_service(string);
            vm.registers[1] = hbvm::value::Value(ret as u64);
        }
    }
    // let buffer_id_raw = &msg_vec[0..8];
    // let mut arr = [0u8; 8];
    // arr.copy_from_slice(&buffer_id_raw);
    // let buffer_id = u64::from_le_bytes(arr);
    // info!("BufferID({:x?})", buffer_id);

    // let mut services = SERVICES.lock();
    // let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8");
    // use core::borrow::BorrowMut;
    // services.borrow_mut().0.insert(buffer_id, string);

    Ok(())
}

enum ServiceEventType {
    CreateService = 0,
    // UpdateService = 1,
    DeleteService = 2,
    SearchServices = 3,
}
impl From<u8> for ServiceEventType {
    fn from(value: u8) -> Self {
        use self::*;
        match value {
            0 => Self::CreateService,
            // 1 =>
            2 => Self::DeleteService,
            3 => Self::SearchServices,
            10 => {
                info!("TEST");
                panic!()
            }
            1_u8 | 4_u8..=u8::MAX => todo!(),
        }
    }
}

fn sds_create_service(protocol: &'static str) -> u64 {
    let buff_id = hardware_random_u64();
    let mut services = SERVICES.lock();
    let mut buffers = IPC_BUFFERS.lock();

    let protocol_ = Protocol::from(protocol);
    let mut buff = IpcBuffer::new(false, 0);

    services.0.insert(buff_id, protocol_.clone());
    buff.protocol = protocol_;
    buffers.insert(buff_id, buff);

    trace!("BufferID({}) => {}", buff_id, protocol);
    // let a: protocol::Protocol = protocol.into();
    buff_id
}

fn sds_search_service(protocol: &str) -> u64 {
    let services = SERVICES.lock();
    let compare = Protocol::from(protocol);
    for (bid, protocol_canidate) in &services.0 {
        trace!("BID-{bid} protocol_canidate {:?}", protocol_canidate);
        if protocol_canidate == &compare {
            trace!("BufferID({}) => {}", bid, protocol);
            return *bid;
        }
    }
    0
}