use {
    crate::holeybytes::{
        ecah::LogError,
        kernel_services::{block_read, mem_serve},
        Vm,
    },
    alloc::alloc::alloc_zeroed,
    log::{debug, info},
};

pub enum MemoryServiceError {
    InvalidMemoryFormat,
}
#[derive(Debug)]
pub enum MemoryQuotaType {
    NoQuota = 0,
    SoftQuota = 1,
    HardQuota = 2,
    KillQuota = 3,
}

fn alloc_page(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), MemoryServiceError> {
    let mut val = alloc::vec::Vec::new();
    for _ in 0..4096 {
        val.push(0);
    }
    info!("Block address: {:?}", val.as_ptr());
    vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
    vm.registers[2] = hbvm::value::Value(4096);
    Ok(())
}

pub fn memory_msg_handler(
    vm: &mut Vm,
    mem_addr: u64,
    length: usize,
) -> Result<(), MemoryServiceError> {
    let mut msg_vec = block_read(mem_addr, length);
    let msg_type = msg_vec[0];

    msg_vec.remove(0);
    match msg_type {
        0 => {
            let page_count = msg_vec[0];
            msg_vec.remove(0);

            let mptr_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
            let mptr: u64 = u64::from_le_bytes(mptr_raw);

            log::debug!("Allocating {} pages @ {:x}", page_count, mptr);

            let mut val = alloc::vec::Vec::new();
            for _ in 0..(page_count as isize * 4096) {
                val.push(0);
            }
            vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
        }
        1 => {
            let page_count = msg_vec[0];
            msg_vec.remove(0);
        }
        2 => {
            use MemoryQuotaType::*;
            let quota_type = match msg_vec[0] {
                0 => NoQuota,
                1 => SoftQuota,
                2 => HardQuota,
                3 => KillQuota,
                _ => NoQuota,
            };
            msg_vec.remove(0);
            let hid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
            let hid: u64 = u64::from_le_bytes(hid_raw);
            for _ in 0..8 {
                msg_vec.remove(0);
            }

            let pid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
            let pid: u64 = u64::from_le_bytes(hid_raw);
            for _ in 0..8 {
                msg_vec.remove(0);
            }

            debug!(
                "Setting HID-{:x}:PID-{:x}'s quota type to {:?}",
                hid, pid, quota_type
            )
        }
        3 => {
            let page_count = msg_vec[0];
            log::debug!(" {} pages", page_count);
            msg_vec.remove(0);
        }

        _ => {
            log::debug!("Unknown memory service message type: {}", msg_type);
        }
    }

    Ok(())
}