use bevy::{platform::collections::HashMap, prelude::*};

use super::{IntoMenuItemInternal, ItemPosition, MenuItem, MenuItemInternal};

#[derive(Debug, Clone)]
pub struct Menus<TriggerState, NavState>
where
    TriggerState: States,
    NavState: States,
{
    pub(super) start: NavState,
    pub(super) closed_when: NavState,
    /// The state needed to trigger this set of menus
    pub(super) trigger: TriggerState,
    pub(super) menus: HashMap<NavState, Menu<NavState>>,
}

#[derive(Debug, Clone)]
pub struct Menu<ParentNavState: States> {
    pub(super) menu_items: Vec<MenuItemInternal<ParentNavState>>,
}

impl<TriggerState, NavState> Menus<TriggerState, NavState>
where
    TriggerState: States,
    NavState: States + Default,
{
    pub fn new(trigger: TriggerState, closed_when: NavState) -> Self {
        Self {
            trigger,
            closed_when,
            start: NavState::default(),
            menus: HashMap::new(),
        }
    }
}

impl<T, NavState> Menus<T, NavState>
where
    T: States,
    NavState: States,
{
    pub fn add_menu(mut self, state: NavState, menu: Menu<NavState>) -> Self {
        self.menus.insert(state, menu);
        self
    }
}

impl<ParentNavState: States> Menu<ParentNavState> {
    pub fn new() -> Self {
        Self {
            menu_items: Vec::new(),
        }
    }

    /// Adds `items` in the default `ItemPosition::MainView`.
    pub fn add_items(mut self, items: &[&dyn MenuItem<ParentNavState>]) -> Self {
        self.add_items_positioned(ItemPosition::MainView, items)
    }

    pub fn add_items_positioned(
        mut self,
        position: ItemPosition,
        items: &[&dyn MenuItem<ParentNavState>],
    ) -> Self {
        items
            .iter()
            .map(|it| (*it).item())
            .collect_into(&mut self.menu_items);
        self
    }
}
