//! Fixed bottom status strip.

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

use crate::history::EditorHistory;
use crate::operators::ActiveOperator;
use crate::project::collaboration::{file_status_indicator_ui, CollaborationState};
use crate::scene_io::SceneIo;
use crate::state::{EditorMode, PlayPaused};

use super::theme::{status_bar_frame, ACCENT, SELECTION, SUCCESS, TEXT, TEXT_DIM, TEXT_MUTED};
use super::widgets::phosphor_icon;

pub fn status_bar_ui(
    world: &World,
    root_ui: &mut egui::Ui,
    selected: &SelectedEntities,
    mode: EditorMode,
) {
    egui::Panel::bottom("editor_status_bar")
        .exact_size(27.0)
        .frame(status_bar_frame())
        .show_inside(root_ui, |ui| {
            ui.spacing_mut().item_spacing.x = 10.0;
            egui::containers::Sides::new()
                .shrink_left()
                .truncate()
                .show(
                    ui,
                    |ui| {
                        let status = primary_status_line(world);
                        ui.label(
                            egui::RichText::new("●")
                                .color(if world.resource::<SceneIo>().dirty {
                                    ACCENT
                                } else {
                                    SUCCESS
                                })
                                .small(),
                        );
                        ui.add(
                            egui::Label::new(egui::RichText::new(&status).color(TEXT_DIM))
                                .truncate(),
                        )
                        .on_hover_text(status);
                    },
                    |ui| {
                        if let (Some(state), Some(path)) = (
                            world.get_resource::<CollaborationState>(),
                            world.resource::<SceneIo>().active_path.as_deref(),
                        ) {
                            let status = state.file_status(path);
                            if status.indicator().is_some() {
                                let _ = file_status_indicator_ui(ui, &status, path);
                                ui.separator();
                            }
                        }
                        let (mode_icon, mode_label, mode_color) = match mode {
                            EditorMode::Editing => (icons::PENCIL_SIMPLE, "EDIT", ACCENT),
                            EditorMode::Playing => {
                                if world.resource::<PlayPaused>().0 {
                                    (icons::PAUSE, "PAUSED", ACCENT)
                                } else {
                                    (icons::PLAY, "PLAYING", SUCCESS)
                                }
                            }
                        };
                        ui.label(phosphor_icon(mode_icon, 13.0).color(mode_color));
                        ui.label(
                            egui::RichText::new(mode_label)
                                .color(mode_color)
                                .strong()
                                .small(),
                        );

                        ui.separator();

                        let count = selected.len();
                        let selection = match count {
                            0 => "None".to_string(),
                            1 => "1 selected".to_string(),
                            _ => format!("{count} selected"),
                        };
                        ui.label(egui::RichText::new(selection).color(if count == 0 {
                            TEXT_MUTED
                        } else {
                            SELECTION
                        }));

                        ui.label(
                            egui::RichText::new(world.resource::<EditorHistory>().status.clone())
                                .color(TEXT_DIM),
                        );

                        if let Some(operator_label) = world.resource::<ActiveOperator>().label() {
                            ui.label(egui::RichText::new(operator_label).color(TEXT));
                        }

                        #[cfg(feature = "hot-reload")]
                        if let Some(hot) = world.get_resource::<crate::hot_reload::HotReloadState>()
                        {
                            ui.label(egui::RichText::new(hot.label.clone()).color(TEXT));
                        }
                    },
                );
        });
}

fn scene_line(scene_io: &SceneIo) -> String {
    let dirty = if scene_io.dirty { " *" } else { "" };
    let recovery = if scene_io.recovery_snapshot.is_some() {
        " [recovery]"
    } else {
        ""
    };
    format!("Scene: {}{dirty}{recovery}", scene_io.active_path_label())
}

fn primary_status_line(world: &World) -> String {
    let scene_io = world.resource::<SceneIo>();
    format!("{}  |  {}", scene_io.status, scene_line(scene_io))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn scene_line_marks_unsaved_changes() {
        let mut scene_io = SceneIo::default();
        assert!(!scene_line(&scene_io).ends_with('*'));

        scene_io.mark_dirty();
        assert!(scene_line(&scene_io).ends_with('*'));

        scene_io.recovery_snapshot = Some("recovery.scn.ron".into());
        assert!(scene_line(&scene_io).ends_with("[recovery]"));
    }
}
