use std::fmt::Display;

#[derive(Debug)]
pub(crate) struct Register {
    pub content: Vec<u32>,
    pub cursor: usize,
}

impl Display for Register {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "[{}]",
            self.content
                .iter()
                .enumerate()
                .map(|(i, v)| if i == self.cursor && self.content.len() > 1 {
                    format!("[{v}]")
                } else {
                    format!("{v}")
                })
                .collect::<Vec<String>>()
                .join(" ")
        )
    }
}

impl Register {
    pub fn get(&self) -> u32 {
        return *self.content.get(self.cursor).unwrap();
    }

    pub fn left(&mut self, by: u32) {
        self.cursor =
            ((self.cursor as i32) - (by as i32)).rem_euclid(self.content.len() as i32) as usize;
    }

    pub fn right(&mut self, by: u32) {
        self.cursor = (self.cursor + by as usize) % self.content.len();
    }

    pub fn remove(&mut self) -> u32 {
        let val = self.content[self.cursor];
        self.content[self.cursor] = 0;
        val
    }

    pub fn add(&mut self, value: u32) {
        self.insert(self.get().checked_add(value).unwrap_or_default())
    }

    pub fn insert(&mut self, value: u32) {
        self.content[self.cursor] = value;
    }

    pub(crate) fn sub(&mut self, value: u32) {
        self.insert(self.get().checked_sub(value).unwrap_or_default())
    }
}

#[derive(PartialEq, Eq, Debug)]
pub enum ExecutionResult {
    Full(Vec<Vec<u32>>),
    List(Vec<u32>),
    Number(u32),
}