extern "C" {
    fn __k3_kv_open_default() -> u64;
    fn __k3_kv_get(db_ptr: u64, key_ptr: u32) -> u32;
    fn __k3_kv_set(db_ptr: u64, key_ptr: u32, value_ptr: u32);
    fn __k3_kv_delete(db_ptr: u64, key_ptr: u32);
}

pub struct Db {
    db_ptr: u64,
}

impl Db {
    pub fn open_default() -> Self {
        Self {
            db_ptr: unsafe { __k3_kv_open_default() },
        }
    }

    pub fn get(&self, key: &str) -> Option<String> {
        let mut key_buf = (key.len() as u32).to_le_bytes().to_vec();
        key_buf.extend_from_slice(key.as_bytes());
        let value_ptr = unsafe { __k3_kv_get(self.db_ptr, key_buf.as_ptr() as u32) };
        dbg!(value_ptr);
        if value_ptr == 0 {
            None
        } else {
            let value_ptr = value_ptr as *mut u8;
            let len = u32::from_le_bytes(
                unsafe { std::slice::from_raw_parts(value_ptr, 4) }
                    .try_into()
                    .unwrap(),
            );
            let mut res = vec![0u8; len as usize];
            res.copy_from_slice(unsafe {
                std::slice::from_raw_parts(value_ptr.add(4), len as usize)
            });
            Some(String::from_utf8(res).unwrap())
        }
    }

    pub fn set(&mut self, key: &str, value: String) {
        let mut key_buf = (key.len() as u32).to_le_bytes().to_vec();
        key_buf.extend_from_slice(key.as_bytes());
        let mut value_buf = (value.len() as u32).to_le_bytes().to_vec();
        value_buf.extend_from_slice(value.as_bytes());
        unsafe {
            __k3_kv_set(
                self.db_ptr,
                key_buf.as_ptr() as u32,
                value_buf.as_ptr() as u32,
            );
        }
    }

    pub fn delete(&mut self, key: &str) {
        let mut key_buf = (key.len() as u32).to_le_bytes().to_vec();
        key_buf.extend_from_slice(key.as_bytes());
        unsafe {
            __k3_kv_delete(self.db_ptr, key_buf.as_ptr() as u32);
        }
    }
}
