use crate::prelude::*;

pub(crate) struct MenuPlugin;

impl Plugin for MenuPlugin {
    fn build(&self, app: &mut App) {
        app.init_state::<MenuState>()
            // Initialize menus
            .add_systems(
                // TODO: move this to game.rs or display3d.rs
                OnExit(GameState::Loading),
                init_play_menu,
            )
            // Manage visible/hidden states
            .add_systems(
                Update,
                manage_state_entities::<MenuState>().run_if(state_changed::<MenuState>),
            )
            .add_systems(
                Update,
                (
                    handle_button_press::<GameState>,
                    handle_button_press::<MenuState>,
                    handle_button_press::<TutorialState>,
                )
                    .run_if(any_component_changed::<Interaction>()),
            )
            .add_systems(Update, handle_escape.run_if(just_pressed(KeyCode::Escape)));
    }
}

#[derive(Debug, States, Hash, Default, PartialEq, Eq, Clone, Component)]
pub(crate) enum MenuState {
    #[default]
    Off,
    On,
}

#[derive(Debug, Component)]
pub(crate) struct ButtonAction<S: States + Clone + Component>(pub S);

fn init_play_menu(
    mut commands: Commands,
    tweaks_file: Res<tweak::GameTweaks>,
    tweaks: Res<Assets<tweak::Tweaks>>,
) {
    info!("Initializing Play menu");

    let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks");
    let button_handle = tweak.get_handle::<Image>("buttons_image_resting").unwrap();
    let font_handle = tweak.get_handle::<Font>("buttons_font").unwrap();
    let title_handle = tweak.get_handle::<Image>("title_image").unwrap();
    let title_width_px = tweak.get::<f32>("title_width_px").unwrap();

    commands
        .spawn((
            MenuState::On,
            NodeBundle {
                style: Style {
                    width: Val::Percent(100.0),
                    height: Val::Percent(100.0),
                    justify_content: JustifyContent::Center,
                    align_items: AlignItems::Center,
                    flex_direction: FlexDirection::Column,
                    position_type: PositionType::Absolute,
                    ..default()
                },
                background_color: Color::NONE.into(),
                visibility: Visibility::Hidden,
                ..default()
            },
        ))
        .with_children(|parent| {
            // Title
            parent.spawn(ImageBundle {
                style: Style {
                    width: Val::Px(title_width_px),
                    ..default()
                },
                image: UiImage {
                    texture: title_handle.clone(),
                    ..default()
                },
                ..default()
            });

            // Continue button
            parent
                .spawn((
                    ButtonAction(GameState::Play),
                    ButtonAction(MenuState::Off),
                    ButtonBundle {
                        style: Style {
                            padding: UiRect::all(Val::Px(2.0)),
                            margin: UiRect::all(Val::Px(2.0)),
                            ..default()
                        },
                        image: UiImage {
                            texture: button_handle.clone(),
                            ..default()
                        },
                        ..default()
                    },
                ))
                .with_children(|parent| {
                    parent.spawn(TextBundle {
                        text: Text {
                            sections: vec![TextSection {
                                value: "C o n t i n u e".into(),
                                style: TextStyle {
                                    color: Color::WHITE,
                                    font_size: 12.0,
                                    font: font_handle.clone(),
                                },
                            }],
                            ..default()
                        },
                        style: Style {
                            margin: UiRect::all(Val::Px(10.0)),
                            ..default()
                        },
                        ..default()
                    });
                });

            // Restart button
            parent
                .spawn((
                    ButtonAction(GameState::Restart),
                    ButtonAction(MenuState::Off),
                    ButtonBundle {
                        style: Style {
                            padding: UiRect::all(Val::Px(2.0)),
                            margin: UiRect::all(Val::Px(2.0)),
                            ..default()
                        },
                        image: UiImage {
                            texture: button_handle.clone(),
                            ..default()
                        },
                        ..default()
                    },
                ))
                .with_children(|parent| {
                    parent.spawn(TextBundle {
                        text: Text {
                            sections: vec![TextSection {
                                value: "R e s t a r t".into(),
                                style: TextStyle {
                                    color: Color::WHITE,
                                    font_size: 12.0,
                                    font: font_handle.clone(),
                                },
                            }],
                            ..default()
                        },
                        style: Style {
                            margin: UiRect::all(Val::Px(10.0)),
                            ..default()
                        },
                        ..default()
                    });
                });

            // Tutorial button
            parent
                .spawn((
                    ButtonAction(TutorialState::Intro),
                    ButtonAction(MenuState::Off),
                    ButtonBundle {
                        style: Style {
                            padding: UiRect::all(Val::Px(2.0)),
                            margin: UiRect::all(Val::Px(2.0)),
                            ..default()
                        },
                        image: UiImage {
                            texture: button_handle.clone(),
                            ..default()
                        },
                        ..default()
                    },
                ))
                .with_children(|parent| {
                    parent.spawn(TextBundle {
                        text: Text {
                            sections: vec![TextSection {
                                value: "T u t o r i a l".into(),
                                style: TextStyle {
                                    color: Color::WHITE,
                                    font_size: 12.0,
                                    font: font_handle.clone(),
                                },
                            }],
                            ..default()
                        },
                        style: Style {
                            margin: UiRect::all(Val::Px(10.0)),
                            ..default()
                        },
                        ..default()
                    });
                });

            // Credits button
            parent
                .spawn((
                    ButtonAction(GameState::Credits),
                    ButtonAction(MenuState::Off),
                    ButtonBundle {
                        style: Style {
                            padding: UiRect::all(Val::Px(2.0)),
                            margin: UiRect::all(Val::Px(2.0)),
                            ..default()
                        },
                        image: UiImage {
                            texture: button_handle.clone(),
                            ..default()
                        },
                        ..default()
                    },
                ))
                .with_children(|parent| {
                    parent.spawn(TextBundle {
                        text: Text {
                            sections: vec![TextSection {
                                value: "C r e d i t s".into(),
                                style: TextStyle {
                                    color: Color::WHITE,
                                    font_size: 12.0,
                                    font: font_handle.clone(),
                                },
                            }],
                            ..default()
                        },
                        style: Style {
                            margin: UiRect::all(Val::Px(10.0)),
                            ..default()
                        },
                        ..default()
                    });
                });

            // Quit button
            parent
                .spawn((
                    ButtonAction(GameState::Quit),
                    ButtonAction(MenuState::Off),
                    ButtonBundle {
                        style: Style {
                            padding: UiRect::all(Val::Px(2.0)),
                            margin: UiRect::all(Val::Px(2.0)),
                            ..default()
                        },
                        image: UiImage {
                            texture: button_handle.clone(),
                            ..default()
                        },
                        ..default()
                    },
                ))
                .with_children(|parent| {
                    parent.spawn(TextBundle {
                        text: Text {
                            sections: vec![TextSection {
                                value: "Q  u  i  t".into(),
                                style: TextStyle {
                                    color: Color::WHITE,
                                    font_size: 12.0,
                                    font: font_handle.clone(),
                                },
                            }],
                            ..default()
                        },
                        style: Style {
                            margin: UiRect::all(Val::Px(10.0)),
                            ..default()
                        },
                        ..default()
                    });
                });
        });
}

fn handle_escape(
    game_state: Res<State<GameState>>,
    tutorial_state: Res<State<TutorialState>>,
    menu_state: Res<State<MenuState>>,
    mut next_game_state: ResMut<NextState<GameState>>,
    mut next_menu_state: ResMut<NextState<MenuState>>,
    mut next_tutorial_state: ResMut<NextState<TutorialState>>,
) {
    match game_state.get() {
        GameState::Loading => error!("No menu while loading!"),
        // State(Play): ...
        GameState::Play => {
            match tutorial_state.get() {
                // State(Tutorial::None): Escape -> Play Menu
                TutorialState::None => {
                    match menu_state.get() {
                        // State(Menu::None): Escape -> Show Menu
                        MenuState::Off => next_menu_state.set(MenuState::On),
                        // State(Menu::Play): Escape -> Hide menu
                        MenuState::On => next_menu_state.set(MenuState::Off),
                    }
                }
                // State(Tutorial::*): Escape -> Quit Tutorial
                _ => {
                    next_tutorial_state.set(TutorialState::None);
                }
            }
        }
        // State(Endgame): Escape -> Quit game
        GameState::Endgame => {
            next_game_state.set(GameState::Quit);
        }
        // State(Credits): Escape -> Play + Menu
        GameState::Credits => {
            next_game_state.set(GameState::Play);
            next_menu_state.set(MenuState::On);
        }
        // State(Intro): Escape -> Play
        GameState::Intro => {
            next_game_state.set(GameState::Title);
        }
        GameState::Title => {
            next_game_state.set(GameState::Play);
        }
        GameState::Restart | GameState::Quit => {
            panic!("This shouldn't be possible!");
        }
    }
}

fn handle_button_press<S: States + Clone + Component>(
    events: Query<(&Interaction, &ButtonAction<S>), Changed<Interaction>>,
    mut next_state: ResMut<NextState<S>>,
) {
    events
        .iter()
        .filter_map(|(interaction, button_action)| {
            (*interaction == Interaction::Pressed).then_some(button_action)
        })
        .for_each(|ButtonAction(ba)| next_state.set(ba.clone()));
}
