use crate::system::*;

pub struct Internal {
    subsystems:[Option<Sender<Query>>; System::_MAX as usize],
}

impl Internal {
    pub fn thread(tx:Sender<Query>, rx:Receiver<Query>)
    {
        let mut sv = Internal {
            subsystems:std::array::from_fn(|_| None),
        };
        sv.subsystems[System::Supervisor as usize] = Some(tx);

        while let Ok(query) = rx.recv() {
            match query.data {
                QueryData::Supervisor(request) => match request {
                    SupervisorQuery::Start {
                        system,
                    } => if sv.subsystems[system as usize].is_none() {
                        let supervisor_responder = sv.subsystems[System::Supervisor as usize].clone();

                        if let Ok(channel) = match system {

                            System::Window => WindowManager::start(supervisor_responder),

                            _ => { Err(Error::new()) }
                        } {
                            for i in 0..sv.subsystems.len() {

                                // Notify active subsystems that subsystem has started.
                                if let Some(tx) = &sv.subsystems[i] {
                                    tx.send(Query::new(None, QueryData::Supervisor(
                                        SupervisorQuery::Status {
                                            system,
                                            channel: Some(channel.clone()),
                                        }
                                    ))).ok();
                                }
                            }

                            if let Some(resp) = query.resp {
                                resp.send(Query::new(None, QueryData::Supervisor(
                                    SupervisorQuery::Status {
                                        system,
                                        channel: Some(channel.clone()),
                                    }
                                ))).ok();
                            }

                            sv.subsystems[system as usize] = Some(channel);
                        } else {
                            // Log subsystem startup error
                            
                        }
                    }

                    SupervisorQuery::Stop {
                        system,
                    } => if let Some(tx) = &sv.subsystems[system as usize] {

                        // Send shutdown instruction to subsystem.
                        tx.send(Query::new(None, QueryData::Supervisor(
                            SupervisorQuery::Stop {
                                system,
                            }
                        ))).ok();

                        // Drop channel.
                        sv.subsystems[system as usize] = None;
                    }

                    SupervisorQuery::Status {
                        system,
                        channel: _,
                    } => if let Some(from) = query.resp {
                        from.send(Query::new(None, QueryData::Supervisor(
                            SupervisorQuery::Status {
                                system,
                                channel:sv.subsystems[system as usize].clone(),
                            }
                        ))).ok();
                    }

                    _ => { }
                }
                _ => { }
            }
        }
    }
}
