/src/task/entry.rs
use core::fmt;

use crate::capabilities::{CapToken, MAX_CAPS, CapType};
use crate::mpu::MemoryMap;
use crate::task::TaskId;
use crate::timer::Ticks;

#[derive(Debug, PartialEq)]
pub enum TaskState {
    /// Task running normally; eligible to be scheduled
    Running,
    /// Blocked waiting for the fulfillment of a device indicated by
    /// the capability type contained within.
    Blocked(CapType),
    /// Waiting for the current number of ticks to equal the value
    /// within.
    Sleeping(Ticks),
    /// The task is exiting and will be removed on the next scheduling pass
    Exiting,
}

impl fmt::Display for TaskState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TaskState::Running => write!(f, "running"),
            TaskState::Blocked(c) => write!(f, "blocked {}", c),
            TaskState::Sleeping(_) => write!(f, "sleeping"),
            TaskState::Exiting => write!(f, "exiting"),
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone)]
pub(crate) struct TaskRegisters {
    pub r0: u32,
    pub r1: u32,
    pub r2: u32,
    pub r3: u32,
    pub r12: u32,
    pub lr: u32,
    pub pc: u32,
    pub xpsr: u32,
    pub sp: u32,
    pub r8: u32,
    pub r9: u32,
    pub r10: u32,
    pub r11: u32,
    pub r4: u32,
    pub r5: u32,
    pub r6: u32,
    pub r7: u32,
}

impl TaskRegisters {
    pub fn new() -> TaskRegisters {
        TaskRegisters {
            r0: 0,
            r1: 0,
            r2: 0,
            r3: 0,
            r4: 0,
            r5: 0,
            r6: 0,
            r7: 0,
            r8: 0,
            r9: 0,
            r10: 0,
            r11: 0,
            r12: 0,
            sp: 0,
            lr: 0,
            pc: 0,
            xpsr: 0x01000000,   // Default value sets thread mode, which must always be set
        }
    }
}

#[derive(Debug)]
pub(crate) struct TaskEntry {
    pub id: TaskId,
    pub name: heapless::String<8>,
    pub regs: TaskRegisters,
    pub mem_map: MemoryMap,
    pub state: TaskState,
    pub priority: u8,
    pub io_ready: bool,
    pub ticks_ran: u32,
    pub caps: heapless::Vec<CapToken, MAX_CAPS>,
}

impl TaskEntry {
    pub fn has_capability(&self, cap: CapType) -> bool {
        self.caps.iter().any(|c| c.captype() == cap)
    }
}