
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]

//! Crate burritos ((BurritOS Using Rust Really Improves The Operating System)
//! 
//! Burritos is an educational operating system written in Rust
//! running on RISC-V emulator.

/// Contain hardware simulated part of the machine
mod simulator;
mod kernel;
/// module containing useful tools which can be use in most part of the OS to ease the development of the OS
pub mod utility;

use std::{rc::Rc, cell::RefCell};

use kernel::{system::System, thread::Thread, process::Process};
use simulator::{machine::Machine, loader};


use clap::Parser;
use utility::cfg::read_settings;

#[derive(Parser, Debug)]
#[command(name = "BurritOS", author, version, about = "Burritos (BurritOS Using Rust Really Improves The Operating System)

Burritos is an educational operating system written in Rust
running on RISC-V emulator.", long_about = None)]
/// Launch argument parser
struct Args {
    /// Enable debug mode.
    /// 0 to disable debug,
    /// 1 to enable machine debug,
    /// 2 to enable system debug,
    /// 3 to enable all debug
    #[arg(short, long, value_parser = clap::value_parser!(u8).range(0..=3), default_value_t = 0)]
    debug: u8,
    /// Path to the executable binary file to execute
    #[arg(short = 'x', long, value_name = "PATH")]
    executable: String
}

fn main() {
    let args = Args::parse();

    let mut machine = Machine::new(args.debug & 1 != 0, read_settings().unwrap());
    let (loader, ptr) = loader::Loader::new(args.executable.as_str(), &mut machine, 0).expect("An error occured while parsing the program");
    
    let mut system = System::new(args.debug & 2 != 0);

    let thread_exec = Thread::new(args.executable.as_str());
    let thread_exec = Rc::new(RefCell::new(thread_exec));
    system.get_thread_manager().get_g_alive().push(Rc::clone(&thread_exec));

    let owner1 = Process { num_thread: 0 };
    let owner1 = Rc::new(RefCell::new(owner1));
    system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr + machine.page_size, -1);
    
    let to_run = system.get_thread_manager().find_next_to_run().unwrap();
    system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run));

    machine.run(&mut system);
}
