use crate::arch::drivers::sysinfo::master;
use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE};
use crate::{time::fetch_time, KERNEL_STATE};
// use genfs::{Fs, OpenOptions};
use kernel::allocator::ALLOCATOR;
// use rhai::Engine;
use spin::Lazy;
use x86_64::instructions::interrupts::{disable, enable};

pub const RHAISHELL_VERSION: &str = "0.1.0";

pub static KEYBUFF: spin::Mutex<Vec<char>> = spin::Mutex::new(Vec::new());
pub static CURRENT_DIR: Lazy<spin::Mutex<String>> = Lazy::new(|| spin::Mutex::new("/".to_string()));

#[cfg(target_arch = "riscv64")]
pub fn shell() {}

// #[cfg(target_arch = "x86_64")]
// pub fn shell() {
//     let _current_dir = "/".to_string();
//     let engine = engine_construction();
//     let mut scope = rhai::Scope::new();

//     println!("Rhaishell v{}", RHAISHELL_VERSION);

//     let mut buf = String::new();
//     print!("> ");

//     loop {
//         match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) {
//             Some('\n') => {
//                 if buf == "quit" {
//                     println!("Bye!");
//                     break;
//                 }

//                 match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &buf) {
//                     Ok(o) => println!("{o}"),

//                     Err(e) => println!("Eval error: {e}"),
//                 };

//                 buf.clear();
//                 print!("> ");
//             }
//             Some('\u{0008}') => {
//                 buf.pop();
//             }

//             Some('\u{0009}') => {
//                 buf.push(' ');
//                 buf.push(' ');
//                 buf.push(' ');
//                 buf.push(' ');
//             }

//             Some(chr) => buf.push(chr),
//             None => (),
//         }
//     }
// }

pub fn afetch() {
    let kstate = KERNEL_STATE.lock();

    let tick_time = fetch_time();

    disable();
    let allocator = ALLOCATOR.lock();
    let size = allocator.size();
    let used = allocator.used();
    enable();

    println!(
        include_str!("balloon.txt"),
        kstate.hostname,
        RELEASE_TYPE,
        KERNEL_VERSION,
        tick_time,
        master().unwrap().brand_string().unwrap(),
        // "",
        // mem
        used,
        size
    );
    drop(kstate);
}

pub fn set_hostname(name: String) {
    let mut kstate = KERNEL_STATE.lock();
    kstate.hostname = name;
}

/// Examine a memory pointer
pub fn peek_memory(ptr: i64) -> i64 {
    unsafe { *(ptr as *const u8) as _ }
}

pub fn poke_memory(ptr: i64, val: i64) {
    match val.try_into() {
        Ok(val) => unsafe { *(ptr as *mut u8) = val },
        Err(_) => error!("{val} cannot be converted into u8"),
    }
}

// pub fn ls() {
//     let current_dir = CURRENT_DIR.lock();

//     let fs = &*FILE_SYSTEM.lock();

//     let file = fs
//         .open(current_dir.as_bytes(), OpenOptions::new().read(true))
//         .unwrap();

//     let mut files = file.directory().unwrap();
//     println!("current dir: {}", *current_dir);
//     while let Some(Ok(entry)) = files.next() {
//         let inode_name = entry.name;
//         let s = String::from_utf8_lossy(&inode_name);
//         println!("{}", s);
//     }
// }

pub fn log_dump() {
    use crate::network::socket::SimpleSock;
    use crate::relib::network::socket::Socket;
    let log_socket_id = SimpleSock::grab_socket("Logger".to_string());
    match log_socket_id {
        Some(mut log_socket_id) => {
            let log = log_socket_id.peek();

            match log {
                crate::network::socket::SocketReturns::ReadOk(ok) => {
                    for x in ok.iter() {
                        print!("{}", *x as char);
                    }
                }

                crate::network::socket::SocketReturns::ReadIndexOutOfBounds => todo!(),
                crate::network::socket::SocketReturns::WriteOk => todo!(),
            }
        }
        None => warn!("No socket found for Logger"),
    }
}

// pub fn echo_file(path: String) {
//     let mut current_dir = CURRENT_DIR.lock();

//     let fs = &*FILE_SYSTEM.lock();

//     current_dir.push_str(&path);

//     let file = fs
//         .open(current_dir.as_bytes(), OpenOptions::new().read(true))
//         .unwrap();

//     if file.is_dir() {
//         println!("{} is a directory", path);
//     } else {
//         let mut file_contents = Vec::new();

//         let _ret = file.read_to_end(&mut file_contents).unwrap();

//         let file_contents_str = String::from_utf8_lossy(&file_contents);

//         println!("{}", file_contents_str);
//     }
// }

// pub fn change_directory(path: String) {
//     let mut current_dir = CURRENT_DIR.lock();

//     let _fs = &*FILE_SYSTEM.lock();
//     if path == "." || path == ".." {
//         let mut split_dir = current_dir.split('/').collect::<Vec<&str>>();
//         let mut new_dir = String::new();
//         split_dir.remove(split_dir.len() - 1);
//         println!("{:?}", split_dir);
//         if split_dir.is_empty() {
//             new_dir = "/".to_string();
//         } else {
//             for x in split_dir {
//                 new_dir.push_str(x);
//                 new_dir.push('/');
//             }
//         }
//         *current_dir = new_dir;
//     } else {
//         if !current_dir.ends_with('/') {
//             current_dir.push('/');
//         }
//         current_dir.push_str(&path);
//     }
// }

// fn engine_construction() -> Engine {
//     let mut engine = rhai::Engine::new();

//     engine.on_print(|x| println!("{}", x));
//     engine.on_debug(|x, src, pos| {
//         let src = src.unwrap_or("unknown");
//         println!("DEBUG: {} at {:?}: {}", src, pos, x);
//         debug!("{} at {:?}: {}", src, pos, x);
//     });

//     engine.register_fn("afetch", afetch);
//     engine.register_fn("set_hostname", set_hostname);
//     engine.register_fn("shutdown", shutdown);
//     engine.register_fn("peek", peek_memory);
//     engine.register_fn("poke", poke_memory);
//     engine.register_fn("sloop", sloop);
//     engine.register_fn("log_dump", log_dump);
//     // engine.register_fn("ls", ls);

//     engine
// }
