use std::sync::mpsc::SyncSender;

use models::ComponentId;

#[derive(Debug)]
pub struct TransitionInfo {
    check_mode_reached: bool,
}

#[derive(Debug)]
pub struct ChildModes {
    mgm_assembly_mode: models::acs::mgm_assembly::Mode,
    mgt_mode: models::acs::mgt::Mode,
    controller_mode: models::acs::ctrl::Mode,
}

#[derive(Debug)]
pub struct TransitionCommands {
    mgm_assembly_mode: Option<(models::acs::mgm_assembly::Mode, TransitionInfo)>,
    mgt_mode: Option<(models::acs::mgt::Mode, TransitionInfo)>,
    controller_mode: Option<(models::acs::ctrl::Mode, TransitionInfo)>,
}

const OFF_SEQUENCE: [TransitionCommands; 2] = [
    TransitionCommands {
        mgm_assembly_mode: None,
        mgt_mode: None,
        controller_mode: Some((
            models::acs::ctrl::Mode::Passive,
            TransitionInfo {
                check_mode_reached: true,
            },
        )),
    },
    TransitionCommands {
        mgm_assembly_mode: Some((
            models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Off),
            TransitionInfo {
                check_mode_reached: false,
            },
        )),
        mgt_mode: Some((
            models::acs::mgt::Mode::Off,
            TransitionInfo {
                check_mode_reached: false,
            },
        )),
        controller_mode: None,
    },
];

const SAFE_SEQUENCE: [TransitionCommands; 2] = [
    TransitionCommands {
        mgm_assembly_mode: Some((
            models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Normal),
            TransitionInfo {
                check_mode_reached: false,
            },
        )),
        mgt_mode: Some((
            models::acs::mgt::Mode::Normal,
            TransitionInfo {
                check_mode_reached: false,
            },
        )),
        controller_mode: None,
    },
    TransitionCommands {
        mgm_assembly_mode: None,
        mgt_mode: None,
        controller_mode: Some((
            models::acs::ctrl::Mode::Safe,
            TransitionInfo {
                check_mode_reached: false,
            },
        )),
    },
];

#[derive(Debug)]
pub struct ModeRequestSenders {
    mode_request_ctrl: SyncSender<models::acs::ctrl::request::ModeRequest>,
    mode_request_assy: SyncSender<models::acs::mgm_assembly::request::ModeRequest>,
    mode_request_mgt: SyncSender<models::acs::mgt::request::ModeRequest>,
}

#[derive(Debug)]
pub struct ModeReportReceivers {
    mode_response_ctrl: SyncSender<models::acs::ctrl::response::ModeReport>,
    mode_response_assy: SyncSender<models::acs::mgm_assembly::response::ModeReport>,
    mode_response_mgt: SyncSender<models::acs::mgt::response::ModeReport>,
}

#[derive(Debug)]
pub struct Subsystem {
    current_mode: models::acs::subsystem::Mode,
    current_child_modes: Option<ChildModes>,
    mode_request_senders: ModeRequestSenders,
    mode_report_receivers: ModeReportReceivers,
}

impl Subsystem {
    pub const ID: ComponentId = ComponentId::AcsSubsystem;

    pub fn new(
        mode_request_senders: ModeRequestSenders,
        mode_report_receivers: ModeReportReceivers,
    ) -> Self {
        Self {
            current_mode: models::acs::subsystem::Mode::Off,
            current_child_modes: None,
            mode_request_senders,
            mode_report_receivers,
        }
    }
}
