#[derive(PartialEq, Clone, Debug)]
pub enum AluComponentStatus {
    /// The ALU is off.
    PoweredOff,

    /// The ALU is powered on and waiting for user's instruction.
    StandBy,

    /// The ALU is running a program.
    ProgramRunning,

    /// The ALU was running a program and stopped waiting for user input.
    WaitingInput
}

impl AluComponentStatus {
    /// Change status to powered off.
    /// There are no prerequisite for such transition.
    pub fn power_off(&mut self) {
        *self = AluComponentStatus::PoweredOff;
    }

    /// Change status to stand by.
    /// There are no prerequisite for such transition.
    pub fn stand_by(&mut self) {
        *self = AluComponentStatus::StandBy;
    }

    /// if the current status matches the required one,
    /// update status to next status. Panic otherwise.
    /// Required previous statuses: stand by.
    fn update(&mut self, required_status: AluComponentStatus, next_status: AluComponentStatus) {
        if *self == required_status {
            *self = next_status;
        } else {
            panic!("Invalid ALU status transition from {:?} to {:?}", *self, next_status);
        }
    }

    /// Change status to programm running.
    /// Required previous statuses: stand by.
    pub fn program_started(&mut self) {
        self.update(AluComponentStatus::StandBy, AluComponentStatus::ProgramRunning);
    }

    /// Change status to waiting input.
    /// Required previous statuses: program running.
    pub fn wait_user_input(&mut self) {
        self.update(AluComponentStatus::ProgramRunning, AluComponentStatus::WaitingInput);
    }

    /// Change status to programm running.
    /// Required previous statuses: waiting input.
    pub fn program_restarted(&mut self) {
        self.update(AluComponentStatus::WaitingInput, AluComponentStatus::ProgramRunning);
    }
}

