use super::{ComponentInspector, EditorContext};
use nightshade::ecs::prefab::resources::animation_cache_names;
use nightshade::prelude::*;

pub struct AnimationInspector;

impl ComponentInspector for AnimationInspector {
    fn name(&self) -> &str {
        "Animation Player"
    }

    fn has_component(&self, world: &World, entity: Entity) -> bool {
        world.entity_has_animation_player(entity)
    }

    fn add_component(&self, world: &mut World, entity: Entity) {
        world.add_components(entity, ANIMATION_PLAYER);
        world.set_animation_player(entity, AnimationPlayer::default());
    }

    fn remove_component(&self, world: &mut World, entity: Entity) {
        world.remove_animation_player(entity);
    }

    fn ui(
        &mut self,
        world: &mut World,
        entity: Entity,
        ui: &mut egui::Ui,
        _editor: &mut EditorContext,
    ) {
        let cached_names: Vec<String> = animation_cache_names(&world.resources.animation_cache)
            .cloned()
            .collect();

        let player_clip_names: Vec<String> = world
            .get_animation_player(entity)
            .map(|p| p.clips.iter().map(|c| c.name.clone()).collect())
            .unwrap_or_default();

        let mut clip_to_add: Option<String> = None;

        if let Some(player) = world.get_animation_player_mut(entity) {
            ui.label(format!("Clips: {}", player.clips.len()));

            let mut clip_to_play = None;
            let mut clip_to_remove = None;

            if !player.clips.is_empty() {
                ui.horizontal(|ui| {
                    ui.label("Current Clip:");
                    egui::ComboBox::from_id_salt("animation_clip_selector")
                        .selected_text(
                            player
                                .current_clip
                                .and_then(|index| player.clips.get(index))
                                .map(|clip| clip.name.as_str())
                                .unwrap_or("None"),
                        )
                        .show_ui(ui, |ui| {
                            for (index, clip) in player.clips.iter().enumerate() {
                                let is_selected = player.current_clip == Some(index);
                                if ui.selectable_label(is_selected, &clip.name).clicked() {
                                    clip_to_play = Some(index);
                                }
                            }
                        });
                });

                if let Some(clip_index) = player.current_clip
                    && let Some(clip) = player.clips.get(clip_index)
                {
                    ui.label(format!("Duration: {:.2}s", clip.duration));
                    ui.label(format!("Channels: {}", clip.channels.len()));
                }

                ui.separator();

                ui.horizontal(|ui| {
                    ui.label("Time:");
                    let duration = player
                        .current_clip
                        .and_then(|index| player.clips.get(index))
                        .map(|clip| clip.duration)
                        .unwrap_or(1.0);
                    ui.add(egui::Slider::new(&mut player.time, 0.0..=duration).suffix("s"));
                });

                ui.horizontal(|ui| {
                    ui.label("Speed:");
                    ui.add(
                        egui::DragValue::new(&mut player.speed)
                            .speed(0.1)
                            .range(-5.0..=5.0),
                    );
                });

                ui.horizontal(|ui| {
                    ui.checkbox(&mut player.looping, "Looping");
                });

                ui.separator();

                ui.horizontal(|ui| {
                    if player.playing {
                        if ui.button("Pause").clicked() {
                            player.pause();
                        }
                    } else if ui.button("Play").clicked() {
                        player.resume();
                    }

                    if ui.button("Stop").clicked() {
                        player.stop();
                    }

                    if ui.button("Restart").clicked()
                        && let Some(clip_index) = player.current_clip
                    {
                        player.play(clip_index);
                    }
                });

                ui.label(if player.playing {
                    "Status: Playing"
                } else {
                    "Status: Paused"
                });

                ui.separator();

                ui.collapsing("Loaded Clips", |ui| {
                    for (index, clip) in player.clips.iter().enumerate() {
                        ui.horizontal(|ui| {
                            ui.label(format!("[{}] {}", index, clip.name));
                            if ui.small_button("X").clicked() {
                                clip_to_remove = Some(index);
                            }
                        });
                    }
                });
            }

            if let Some(index) = clip_to_play {
                player.play(index);
            }

            if let Some(index) = clip_to_remove {
                player.clips.remove(index);
                if player.current_clip == Some(index) {
                    player.current_clip = None;
                    player.playing = false;
                } else if let Some(current) = player.current_clip
                    && current > index
                {
                    player.current_clip = Some(current - 1);
                }
            }
        }

        ui.separator();

        ui.collapsing(format!("Animation Cache ({})", cached_names.len()), |ui| {
            if cached_names.is_empty() {
                ui.label("No cached animations");
                ui.label("Load FBX files to populate the cache");
            } else {
                egui::ScrollArea::vertical()
                    .max_height(200.0)
                    .show(ui, |ui| {
                        for name in &cached_names {
                            let already_loaded = player_clip_names.contains(name);
                            ui.horizontal(|ui| {
                                if already_loaded {
                                    ui.add_enabled(false, egui::Button::new("+"))
                                        .on_disabled_hover_text("Already loaded");
                                } else if ui.small_button("+").clicked() {
                                    clip_to_add = Some(name.clone());
                                }
                                ui.label(name);
                            });
                        }
                    });
            }
        });

        if let Some(clip_name) = clip_to_add {
            let clip = world
                .resources
                .animation_cache
                .clips
                .get(&clip_name)
                .cloned();
            if let Some(clip) = clip
                && let Some(player) = world.get_animation_player_mut(entity)
            {
                let index = player.clips.len();
                player.clips.push(clip);
                player.play(index);
            }
        }
    }
}
