/// TODO:
/// * Titles on top left of window/tab
/// *
use bevy::{prelude::*, window::PrimaryWindow};

pub struct GameUiPlugin;

impl Plugin for GameUiPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(PreUpdate, (spawn_nav, spawn_tab, spawn_set, spawn_button))
            .add_systems(Update, (manage_names, manage_tab));
    }
}

/// Component for marking UI Nodes
#[derive(Component, PartialEq)]
pub enum GameUi {
    /// Navigation container
    Nav,
    /// Tab container
    Tab,
    /// Game UI Set
    Set,
    /// Game UI Button
    Button,
}

fn spawn_nav(events: Query<(Entity, &GameUi), Added<GameUi>>, mut commands: Commands) {
    events
        .iter()
        .filter(|(_, ui)| **ui == GameUi::Nav)
        .for_each(|(entity, _)| {
            info!("Spawning Nav UI");
            commands.entity(entity).insert(NodeBundle {
                style: Style {
                    flex_direction: FlexDirection::Row, // ?
                    padding: UiRect::all(Val::Px(3.0)),
                    margin: UiRect::all(Val::Px(3.0)),
                    width: Val::Percent(80.0),
                    max_height: Val::Percent(80.0),
                    overflow: Overflow::clip(),
                    justify_content: JustifyContent::Center,
                    align_items: AlignItems::Center,
                    ..default()
                },
                background_color: BackgroundColor(Color::PURPLE),
                ..default()
            });
        });
}

fn spawn_tab(
    events: Query<(Entity, &GameUi, &Name, &Parent), Added<GameUi>>,
    mut commands: Commands,
) {
    events
        .iter()
        .filter(|(_, ui, _, _)| **ui == GameUi::Tab)
        .for_each(|(entity, _, name, parent)| {
            info!("Spawning Tab");
            // Create container for this tab
            let parent_id = commands
                .spawn(NodeBundle {
                    style: Style {
                        flex_direction: FlexDirection::Column,
                        padding: UiRect::all(Val::Px(3.0)),
                        margin: UiRect::all(Val::Px(3.0)),
                        ..default()
                    },
                    background_color: BackgroundColor(Color::GREEN),
                    ..default()
                })
                .set_parent(parent.get())
                .with_children(|parent| {
                    parent.spawn((GameUi::Button, name.clone(), NodeBundle { ..default() }));
                })
                .id();

            // Insert spawn container with tab
            commands
                .entity(entity)
                .remove::<Name>()
                .insert(NodeBundle {
                    style: Style {
                        flex_direction: FlexDirection::Column,
                        padding: UiRect::all(Val::Px(3.0)),
                        margin: UiRect::all(Val::Px(3.0)),
                        display: Display::None,
                        ..default()
                    },
                    background_color: BackgroundColor(Color::PINK),
                    ..default()
                })
                .set_parent(parent_id);
        });
}

fn spawn_set(events: Query<(Entity, &GameUi), Added<GameUi>>, mut commands: Commands) {
    events
        .iter()
        .filter(|(_, ui)| **ui == GameUi::Set)
        .for_each(|(entity, _)| {
            info!("Spawning UI Set");
            commands.entity(entity).insert(NodeBundle {
                style: Style {
                    flex_direction: FlexDirection::Row,
                    flex_wrap: FlexWrap::Wrap,
                    padding: UiRect::all(Val::Px(3.0)),
                    margin: UiRect::all(Val::Px(3.0)),
                    ..default()
                },
                background_color: BackgroundColor(Color::RED),
                ..default()
            });
        });
}

fn spawn_button(events: Query<(Entity, &GameUi), Added<GameUi>>, mut commands: Commands) {
    events
        .iter()
        .filter(|(_, ui)| **ui == GameUi::Button)
        .for_each(|(entity, _)| {
            info!("Spawning UI Button");
            commands.entity(entity).insert(ButtonBundle {
                style: Style {
                    padding: UiRect::all(Val::Px(3.0)),
                    margin: UiRect::all(Val::Px(3.0)),
                    ..default()
                },
                background_color: BackgroundColor(Color::BLUE),
                ..default()
            });
        });
}

fn manage_names(
    events: Query<(Entity, &Name), (With<GameUi>, Or<(Added<Name>, Changed<Name>)>)>,
    mut commands: Commands,
) {
    events.iter().for_each(|(entity, name)| {
        commands.entity(entity).with_children(|parent| {
            parent
                .spawn(NodeBundle {
                    style: Style {
                        align_self: AlignSelf::FlexStart,
                        padding: UiRect::all(Val::Px(3.0)),
                        margin: UiRect::all(Val::Px(3.0)),
                        ..default()
                    },
                    background_color: BackgroundColor(Color::CRIMSON),
                    ..default()
                })
                .with_children(|parent| {
                    parent.spawn(TextBundle::from_section(
                        name.as_str(),
                        TextStyle { ..default() },
                    ));
                });
        });
    });
}

fn manage_tab(
    events: Query<
        (&Interaction, Entity, &Parent),
        (Changed<Interaction>, With<Button>, With<GameUi>),
    >,
    children: Query<&Children>,
    parents: Query<&Parent>,
    ui_elements: Query<(Entity, &GameUi)>,
    mut styles: Query<&mut Style>,
    mut commands: Commands,
) {
    events
        .iter()
        .for_each(|(interaction, interacted_entity, parent)| {
            // Checks:
            // entity pressed
            // entity is button
            // entity parent is a tab
            //
            // Find all other tabs
            // Display::None all except for tab button

            match interaction {
                Interaction::Pressed => {
                    children.get(parent.get()).iter().for_each(|&children| {
                        children
                            .iter()
                            .filter(|&child| *child != interacted_entity)
                            .for_each(|&child| {
                                let mut style = styles.get_mut(child).expect("child has style");
                                style.display = match style.display {
                                    Display::Flex => Display::None,
                                    Display::None => Display::Flex,
                                    _ => Display::Flex, // Not Reachable
                                }
                            });
                    })
                }
                _ => (),
            }
            // When tab button is clicked
            // For all children of parent (the tab)
            // If selected:
            //   display: Display::Flex,
            // else:
            //   Set display: Display::None,
        });
}
