//! Top editor toolbar (below menu bar): spawn/file left, transport center.

use bevy::prelude::*;
use bevy_egui::egui;
use bevy_inspector_egui::bevy_inspector::hierarchy::SelectedEntities;
use egui_phosphor_icons::icons;

use crate::history::spawn_with_history;
use crate::scene_io::{SceneIo, SceneIoRequest};
use crate::state::{EditorMode, PlayPaused, PlayPossession};
use crate::ui::UiState;
use crate::viewport::brush_tool::start_draw_brush_tool;
use crate::viewport::{editor_spawn_ground_position, snap_translation, ViewportSettings};
use shared::PrimitiveShape;

use super::helpers::{
    light_snapshot, primitive_snapshot, toggle_play_mode, toggle_play_paused, toggle_possession,
};
use super::theme::{brand_mark_frame, toolbar_group_frame, ACCENT, TEXT, TEXT_MUTED};
use super::widgets::{
    icon_button, panel_toolbar_row, phosphor_icon, toolbar_separator, transport_button_large,
};

/// Toolbar strip height (menu bar is separate).
const TOOLBAR_HEIGHT: f32 = 50.0;
const TRANSPORT_WIDTH: f32 = 150.0;
const TRANSPORT_SLOT_STEP: f32 = 50.0;

pub fn editor_toolbar_panel(
    world: &mut World,
    root_ui: &mut egui::Ui,
    selected: &mut SelectedEntities,
) {
    egui::Panel::top("editor_toolbar")
        .exact_size(TOOLBAR_HEIGHT)
        .show_inside(root_ui, |ui| {
            toolbar_ui(world, ui, selected);
        });
}

pub fn toolbar_ui(world: &mut World, ui: &mut egui::Ui, selected: &mut SelectedEntities) {
    let (toolbar_rect, _) = ui.allocate_exact_size(
        egui::vec2(ui.available_width(), TOOLBAR_HEIGHT - 2.0),
        egui::Sense::hover(),
    );

    let center_y = toolbar_rect.center().y;
    let left_rect = egui::Rect::from_min_max(
        egui::pos2(toolbar_rect.left() + 8.0, center_y - 20.0),
        egui::pos2(toolbar_rect.right(), center_y + 20.0),
    );
    let transport_rect = egui::Rect::from_center_size(
        egui::pos2(toolbar_rect.center().x, center_y),
        egui::vec2(TRANSPORT_WIDTH, 46.0),
    );
    let right_rect = egui::Rect::from_min_max(
        egui::pos2(transport_rect.right() + 18.0, center_y - 20.0),
        egui::pos2(toolbar_rect.right() - 8.0, center_y + 20.0),
    );

    let mut left_ui = ui.new_child(
        egui::UiBuilder::new()
            .id_salt("toolbar_left")
            .max_rect(left_rect)
            .layout(egui::Layout::left_to_right(egui::Align::Center)),
    );
    left_ui.spacing_mut().item_spacing.x = 6.0;
    left_toolbar(world, &mut left_ui);

    let mut transport_ui = ui.new_child(
        egui::UiBuilder::new()
            .id_salt("toolbar_transport")
            .max_rect(transport_rect)
            .layout(egui::Layout::left_to_right(egui::Align::Center)),
    );
    transport_ui.spacing_mut().item_spacing.x = 10.0;
    toolbar_group_frame().show(&mut transport_ui, |ui| {
        transport_controls(world, ui);
    });

    let mut right_ui = ui.new_child(
        egui::UiBuilder::new()
            .id_salt("toolbar_scene_documents")
            .max_rect(right_rect)
            .layout(egui::Layout::right_to_left(egui::Align::Center)),
    );
    let editing = *world.resource::<State<EditorMode>>().get() == EditorMode::Editing;
    super::scene_tabs::scene_tabs_chrome(world, &mut right_ui, selected, editing);

    ui.painter().line_segment(
        [toolbar_rect.left_bottom(), toolbar_rect.right_bottom()],
        egui::Stroke::new(1.0, super::theme::BORDER),
    );
    ui.painter().line_segment(
        [
            toolbar_rect.left_bottom() + egui::vec2(8.0, 0.0),
            toolbar_rect.left_bottom() + egui::vec2(134.0, 0.0),
        ],
        egui::Stroke::new(2.0, ACCENT),
    );
}

fn left_toolbar(world: &mut World, ui: &mut egui::Ui) {
    brand_mark_frame().show(ui, |ui| {
        ui.set_min_width(118.0);
        ui.set_min_height(30.0);
        ui.horizontal(|ui| {
            ui.label(phosphor_icon(icons::CROSSHAIR, 19.0).color(ACCENT));
            ui.vertical(|ui| {
                ui.spacing_mut().item_spacing.y = 0.0;
                ui.label(
                    egui::RichText::new("BLACKSITE")
                        .size(11.0)
                        .strong()
                        .color(TEXT),
                );
                ui.label(
                    egui::RichText::new("EDITOR // DEV")
                        .size(9.0)
                        .color(TEXT_MUTED),
                );
            });
        });
    });

    toolbar_group_frame().show(ui, |ui| {
        panel_toolbar_row(ui, |ui| {
            if icon_button(ui, icons::CUBE, "Spawn cube").clicked() {
                spawn_primitive_at_camera(world, PrimitiveShape::Box, "Cube");
            }
            if icon_button(ui, icons::MOUNTAINS, "Spawn ramp").clicked() {
                spawn_primitive_at_camera(world, PrimitiveShape::Ramp, "Ramp");
            }
            if icon_button(ui, icons::SPHERE, "Spawn sphere").clicked() {
                spawn_primitive_at_camera(world, PrimitiveShape::Sphere, "Sphere");
            }
            if icon_button(ui, icons::LIGHTBULB, "Spawn point light").clicked() {
                let pos = camera_ground_spawn(world);
                spawn_with_history(world, light_snapshot("Point Light", pos));
            }
            if icon_button(ui, icons::PENCIL_SIMPLE_LINE, "Draw brush (B)").clicked() {
                start_draw_brush_tool(world);
            }
            let selected_navigation_bounds = world
                .resource::<crate::selection::SelectedEntity>()
                .0
                .filter(|entity| world.get::<shared::NavigationBounds>(*entity).is_some());
            let navigation_tip = if selected_navigation_bounds.is_some() {
                "Bake selected navigation bounds"
            } else {
                "Create navigation bounds"
            };
            if icon_button(ui, icons::PATH, navigation_tip).clicked() {
                if let Some(entity) = selected_navigation_bounds {
                    super::navigation_inspector::bake_bounds(world, entity);
                } else {
                    super::navigation_inspector::spawn_navigation_actor(
                        world,
                        super::navigation_inspector::NavigationActorType::Bounds,
                    );
                }
            }

            toolbar_separator(ui);

            if icon_button(ui, icons::FILE, "New scene").clicked() {
                world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::New);
            }
            if icon_button(ui, icons::FOLDER_OPEN, "Open scene").clicked() {
                world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::Open);
            }
            if icon_button(ui, icons::FLOPPY_DISK, "Save scene").clicked() {
                world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::Save);
            }
            if icon_button(ui, icons::COPY, "Save scene as").clicked() {
                world.resource_mut::<SceneIo>().request = Some(SceneIoRequest::SaveAs);
            }
        });
    });
}

fn transport_controls(world: &mut World, ui: &mut egui::Ui) {
    let mode = *world.resource::<State<EditorMode>>().get();
    match mode {
        EditorMode::Editing => {
            ui.add_space(TRANSPORT_SLOT_STEP);
            let play_clicked =
                transport_button_large(ui, "transport_center", icons::PLAY, "Play (F5)", true)
                    .clicked();
            if play_clicked {
                toggle_play_mode(world);
            }
        }
        EditorMode::Playing => {
            let paused = world.resource::<PlayPaused>().0;
            let pause_icon = if paused { icons::PLAY } else { icons::PAUSE };
            let pause_tip = if paused {
                "Resume simulation (F6)"
            } else {
                "Pause simulation (F6)"
            };
            let pause_clicked =
                transport_button_large(ui, "transport_left", pause_icon, pause_tip, false)
                    .clicked();
            if pause_clicked {
                toggle_play_paused(world);
            }
            let stop_clicked = transport_button_large(
                ui,
                "transport_center",
                icons::STOP,
                "Stop and return to Edit (F5)",
                false,
            )
            .clicked();
            if stop_clicked {
                toggle_play_mode(world);
            }

            let possession = *world.resource::<PlayPossession>();
            let (eject_icon, eject_tip) = match possession {
                PlayPossession::Possessed => (icons::SIGN_OUT, "Eject from player (F8)"),
                PlayPossession::Ejected => (icons::USER, "Possess player (F8)"),
            };
            let possession_clicked =
                transport_button_large(ui, "transport_right", eject_icon, eject_tip, false)
                    .clicked();
            if possession_clicked {
                toggle_possession(world);
            }
        }
    }
}

fn camera_ground_spawn(world: &mut World) -> Vec3 {
    let rect = world.resource::<UiState>().viewport_rect;
    let settings = world.resource::<ViewportSettings>().clone();
    let pos = editor_spawn_ground_position(world, rect);
    snap_translation(pos, &settings)
}

fn spawn_primitive_at_camera(world: &mut World, shape: PrimitiveShape, name: &str) {
    let pos = camera_ground_spawn(world);
    spawn_with_history(world, primitive_snapshot(name, shape, pos));
}
