//! Top menu bar.

use bevy::prelude::*;
use bevy_egui::egui;
use bevy_inspector_egui::bevy_inspector::hierarchy::SelectedEntities;
use egui_dock::DockState;

use crate::history::{apply_command_redo, apply_command_undo, EditorHistory};
use crate::scene_io::{SceneIo, SceneIoRequest};
use crate::settings_ui::{open_project_settings_panel, ProjectSettingsPanel};
use crate::state::{EditorMode, PlayPaused};

use super::diagnostics::{BrushDiagnosticsPanel, DiagnosticsPanel};
use super::dock_tabs::{open_and_focus_tab, tab_is_open, tab_label, PanelNodes, PANEL_TABS};
use super::helpers::{
    delete_selection, duplicate_selection, toggle_play_mode, toggle_play_paused, toggle_possession,
};
use super::layout::reset_and_save_layout;
use super::widgets::menu_item;
use super::EditorTab;

pub fn top_menu_bar(
    world: &mut World,
    root_ui: &mut egui::Ui,
    selected: &SelectedEntities,
    dock_state: &mut DockState<EditorTab>,
    panel_nodes: &mut PanelNodes,
) {
    egui::Panel::top("editor_menu_bar").show_inside(root_ui, |ui| {
        egui::MenuBar::new().ui(ui, |ui| {
            ui.menu_button("File", |ui| {
                if menu_item(ui, "New Scene", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::New);
                    ui.close();
                }
                if menu_item(ui, "Open Scene...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::Open);
                    ui.close();
                }
                if menu_item(ui, "Save", Some("Ctrl+S"), true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::Save);
                    ui.close();
                }
                if menu_item(ui, "Save Scene As...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::SaveAs);
                    ui.close();
                }
                let recovery_available = world.resource::<SceneIo>().recovery_snapshot.is_some();
                if recovery_available {
                    ui.separator();
                    if menu_item(ui, "Restore Recovery Snapshot", None, true).clicked() {
                        world.resource_mut::<SceneIo>().request =
                            Some(SceneIoRequest::RestoreRecovery);
                        ui.close();
                    }
                    if menu_item(ui, "Save Recovery Copy As...", None, true).clicked() {
                        world.resource_mut::<SceneIo>().request =
                            Some(SceneIoRequest::SaveRecoveryCopyAs);
                        ui.close();
                    }
                    if menu_item(ui, "Discard Recovery Snapshot", None, true).clicked() {
                        world.resource_mut::<SceneIo>().request =
                            Some(SceneIoRequest::DiscardRecovery);
                        ui.close();
                    }
                }
                ui.separator();
                if menu_item(ui, "Import Assets...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::ImportAssets);
                    ui.close();
                }
                if menu_item(ui, "Export Selection...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::ExportSelection);
                    ui.close();
                }
                if menu_item(ui, "Save Selection As Prefab...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request =
                        Some(SceneIoRequest::SaveSelectionAsPrefab);
                    ui.close();
                }
                ui.separator();
                if menu_item(ui, "Switch Project...", None, true).clicked() {
                    world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::SwitchProject);
                    ui.close();
                }
                if menu_item(ui, "Reveal Project Folder", None, true).clicked() {
                    let root = world
                        .resource::<crate::project_io::ProjectWorkspace>()
                        .root
                        .clone();
                    let status =
                        match crate::launcher::reveal_project_root(std::path::Path::new(&root)) {
                            Ok(()) => format!("Revealed project folder {root}"),
                            Err(error) => format!("Reveal project folder failed: {error}"),
                        };
                    world.resource_mut::<SceneIo>().set_status(status);
                    ui.close();
                }
                let recent: Vec<(usize, String)> = world
                    .resource::<SceneIo>()
                    .recent_paths
                    .iter()
                    .enumerate()
                    .map(|(index, path)| (index, path.display().to_string()))
                    .collect();
                if !recent.is_empty() {
                    ui.separator();
                    ui.menu_button("Recent Scenes", |ui| {
                        for (index, label) in recent {
                            if menu_item(ui, &label, None, true).clicked() {
                                world.resource_mut::<SceneIo>().request =
                                    Some(SceneIoRequest::OpenRecent(index));
                                ui.close();
                            }
                        }
                    });
                }
            });

            ui.menu_button("Edit", |ui| {
                if menu_item(ui, "Project Settings...", None, true).clicked() {
                    open_project_settings_panel(&mut world.resource_mut::<ProjectSettingsPanel>());
                    ui.close();
                }
                ui.separator();
                let can_undo = world.resource::<EditorHistory>().can_undo();
                let can_redo = world.resource::<EditorHistory>().can_redo();
                if menu_item(ui, "Undo", Some("Ctrl+Z"), can_undo).clicked() {
                    apply_command_undo(world);
                    ui.close();
                }
                if menu_item(ui, "Redo", Some("Ctrl+Y"), can_redo).clicked() {
                    apply_command_redo(world);
                    ui.close();
                }
                ui.separator();
                let has_selection = !selected.as_slice().is_empty();
                if menu_item(ui, "Duplicate", Some("Ctrl+D"), has_selection).clicked() {
                    duplicate_selection(world, selected);
                    ui.close();
                }
                if menu_item(ui, "Delete", Some("Del"), has_selection).clicked() {
                    delete_selection(world, selected);
                    ui.close();
                }
            });

            ui.menu_button("Scene", |ui| {
                if menu_item(ui, "Lighting → Use project sun", None, true).clicked() {
                    super::helpers::use_project_sun(world);
                    ui.close();
                }
                if menu_item(ui, "Lighting → Bake scene sun from project", None, true).clicked() {
                    super::helpers::create_scene_sun_override_from_project_settings(world);
                    ui.close();
                }
                if menu_item(ui, "Create → Post Process Volume", None, true).clicked() {
                    crate::rendering_diagnostics::spawn_post_process_volume_at_camera(world);
                    ui.close();
                }
                ui.separator();
                ui.menu_button("Navigation", |ui| {
                    use super::navigation_inspector::{
                        spawn_navigation_actor, NavigationActorType,
                    };
                    for (label, actor_type) in [
                        ("Create Bounds", NavigationActorType::Bounds),
                        ("Create Obstacle", NavigationActorType::Obstacle),
                        ("Create Area", NavigationActorType::Area),
                        ("Create Link", NavigationActorType::Link),
                    ] {
                        if menu_item(ui, label, None, true).clicked() {
                            spawn_navigation_actor(world, actor_type);
                            ui.close();
                        }
                    }
                    ui.separator();
                    let selected_bounds =
                        selected.as_slice().iter().copied().find(|entity| {
                            world.get::<shared::NavigationBounds>(*entity).is_some()
                        });
                    if menu_item(ui, "Bake Selected Bounds", None, selected_bounds.is_some())
                        .clicked()
                    {
                        if let Some(entity) = selected_bounds {
                            super::navigation_inspector::bake_bounds(world, entity);
                        }
                        ui.close();
                    }
                    if menu_item(ui, "Test Selected Path", None, selected_bounds.is_some())
                        .clicked()
                    {
                        if let Some(entity) = selected_bounds {
                            super::navigation_inspector::query_preview(world, entity);
                        }
                        ui.close();
                    }
                });
            });

            ui.menu_button("Build", |ui| {
                let running = world.resource::<super::build::BuildPanel>().is_running();
                if menu_item(ui, "Build Package", None, !running).clicked() {
                    open_and_focus_tab(dock_state, EditorTab::Build, panel_nodes);
                    super::build::request_build(world, false);
                    ui.close();
                }
                if menu_item(ui, "Build and Run", None, !running).clicked() {
                    open_and_focus_tab(dock_state, EditorTab::Build, panel_nodes);
                    super::build::request_build(world, true);
                    ui.close();
                }
                if menu_item(ui, "Cancel Build", None, running).clicked() {
                    super::build::cancel_build(world);
                    ui.close();
                }
                ui.separator();
                let has_output = world.resource::<super::build::BuildPanel>().has_output();
                if menu_item(ui, "Reveal Output", None, has_output).clicked() {
                    super::build::reveal_last_output(world);
                    ui.close();
                }
            });

            ui.menu_button("View", |ui| {
                if menu_item(ui, "Reset Layout", None, true).clicked() {
                    let layout = reset_and_save_layout(world);
                    *dock_state = layout.dock_state;
                    if let Some(nodes) = layout.panel_nodes {
                        *panel_nodes = nodes;
                    }
                    ui.close();
                }
            });

            ui.menu_button("Window", |ui| {
                for tab in PANEL_TABS {
                    let open = tab_is_open(dock_state, &tab);
                    if ui.selectable_label(open, tab_label(&tab)).clicked() {
                        open_and_focus_tab(dock_state, tab, panel_nodes);
                        ui.close();
                    }
                }
                ui.separator();
                let mut diagnostics = world.resource_mut::<DiagnosticsPanel>();
                if ui.checkbox(&mut diagnostics.open, "Diagnostics").clicked() {
                    ui.close();
                }
                let mut brush_diagnostics = world.resource_mut::<BrushDiagnosticsPanel>();
                if ui
                    .checkbox(&mut brush_diagnostics.open, "Brush Diagnostics")
                    .clicked()
                {
                    ui.close();
                }
                let mut rendering =
                    world.resource_mut::<crate::rendering_diagnostics::RenderingDiagnosticsPanel>();
                if ui.checkbox(&mut rendering.open, "Rendering").clicked() {
                    ui.close();
                }
            });

            ui.menu_button("Play", |ui| {
                let playing = *world.resource::<State<EditorMode>>().get() == EditorMode::Playing;
                let paused = world.resource::<PlayPaused>().0;
                if menu_item(ui, "Toggle Play/Edit", Some("F5"), true).clicked() {
                    toggle_play_mode(world);
                    ui.close();
                }
                if menu_item(ui, "Pause / Resume", Some("F6"), playing).clicked() {
                    toggle_play_paused(world);
                    ui.close();
                }
                let possess_label = if playing {
                    "Possess / Eject"
                } else {
                    "Possess / Eject (while playing)"
                };
                if menu_item(ui, possess_label, Some("F8"), playing).clicked() {
                    toggle_possession(world);
                    ui.close();
                }
                if playing && paused {
                    ui.label("Simulation paused");
                }
            });
        });
    });
}
