#![allow(clippy::empty_loop)]

// use crate::scheduler;

use {
   crate::{
      arch::{init, sloop},
      boot_conf,
      boot_conf::BootConfig,
      capabilities,
      experiments::{
         info::master,
         systeminfo::{KERNEL_VERSION, RELEASE_TYPE},
      },
      file::{File, PathRep},
      relib::network::socket::SimpleSock,
      relib::network::socket::Socket,
      scheduler::SCHEDULER,
   },
   alloc::{
      string::{String, ToString},
      vec,
   },
   core::sync::atomic::{AtomicU64, Ordering::*},
   lazy_static::lazy_static,
   log::*,
};

lazy_static! {
   pub static ref TICK: AtomicU64 = AtomicU64::new(0);
   pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new();
}

/// The main entry point of the kernel
#[no_mangle]
pub fn kernel_main() -> ! {
   init::init();
   log::set_max_level(BOOT_CONF.log_level());

   use crate::scheduler::Priority;
   let mut scheduler = SCHEDULER.lock();

   use Priority::*;

   let mut process_1 = scheduler.new_process(High);
   process_1.capabilities.set_file_access(vec![PathRep {
      location: FileLocations::Home,
      file_name: "test".to_string(),
   }]);
   scheduler.add_process(process_1);
   for ref_process in &scheduler.list {
      trace!("{:?}", ref_process);
   }
   drop(scheduler);

   use crate::proto_filetable::contain::FILE_TABLE;
   use crate::proto_filetable::file::FileLocations;

   let mut file_table = FILE_TABLE.lock();
   let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string());

   new_file.write_bytes(b"Hello, world!");
   file_table.add_file("test", new_file);

   let file = file_table.get_file("test");

   match file {
      Some(file) => {
         let file_bytes = &file.data_pointer;
         let file_string = String::from_utf8(file_bytes.to_vec()).unwrap();
         info!("{}", file_string);
      }
      None => {
         info!("File not found");
      }
   }

   use crate::wasm::WasmProgram;
   let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]);
   trace!("Binary Valid: {:?}", ret.validate_header());

   sloop()
}

/// called by arch specific timers to tick up all kernel related functions
pub fn tick() {
   let mut data = TICK.load(Relaxed);
   data += 1;

   crate::kernel_state::KERNEL_STATE.lock().update_state();

   // let mut scheduler = SCHEDULER.lock();
   // scheduler.bump_exec();

   TICK.store(data, Relaxed)
}

pub fn cpu_socket_startup() {
   let mut cpu_info_socket = SimpleSock::new();
   cpu_info_socket.register_protocol("CPU_INFO".to_string());

   let x = master().unwrap();
   let _xyz = x.brand_string().unwrap();
}

pub fn log_version_data() {
   info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION);
   info!(
      "Brand String: {:?}",
      master().unwrap().brand_string().unwrap()
   );
}
