use alloc::vec::Vec;

use crate::{
    capabilities::Capabilities,
    proc::{Process, PID},
    Priority,
};
/// Add additional wake conditions to the list
pub enum WakeCondition {
    /// Wake when the process has been blocked for a certain amount of time  
    TimerInterrupt(u64),
    SocketRead(PID),
    SocketWrite(PID),
    SocketOpen(PID),
    SocketClose(PID),
    // HardwareEvent,
}

// NOTE: Define what is a sleeping process in the context of the ableOS kernel.
// Blocked processes are processes that are waiting for a certain event to occur.
pub struct BlockedProcess {
    pub pid: PID,
    pub wake_time: u64,
}

pub struct Scheduler {
    pub free_pid: PID,
    pub process_exec_time: u64,
    pub execution_queue: Vec<Process>,
    pub sleeping_queue: Vec<Process>,
    // pub blocked_queue: Vec<BlockedProcess>,
    // / All timed processes sorted by wake time
    // pub timed_blocked_queue: Vec<BlockedProcess>,
}
impl Scheduler {
    /// Create a new scheduler
    pub fn new() -> Self {
        Self {
            free_pid: PID(0),
            process_exec_time: 0,
            execution_queue: Vec::new(),
            sleeping_queue: Vec::new(),
        }
    }

    /// Change the current process to the next process in the list
    pub fn next_process(&mut self) {
        self.process_exec_time = 0;
        let previous_task = self.execution_queue[0].clone();
        self.execution_queue.remove(0);
        self.execution_queue.push(previous_task);
    }

    /// Creates a new process
    /// # Arguments
    /// * `priority` - The priority of the process
    /// # Example
    ///
    /// ```
    /// let mut scheduler = scheduler();
    /// let mut process = scheduler.new_process(Priority::Medium);
    /// ```
    ///
    /// TODO: Add a priority queue
    /// TODO: Add a process queue
    pub fn new_process(&mut self, priority: Priority) -> Process {
        let process = Process {
            id: self.free_pid,
            priority,
            capabilities: Capabilities::empty(),
        };
        self.free_pid.0 += 1;
        process
    }

    pub fn sleep_process(&mut self, process: &mut Process) {
        let sleeping_process = BlockedProcess {
            pid: process.id,
            wake_time: 0,
        };

        self.sleeping_queue.push(process.clone());
        self.execution_queue.remove(0);
    }
}
