use super::{ComponentInspector, EditorContext};
use nightshade::prelude::*;

#[derive(Default)]
pub struct TextInspector;

impl ComponentInspector for TextInspector {
    fn name(&self) -> &str {
        "Text"
    }

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

    fn add_component(&self, world: &mut World, entity: Entity) {
        let text_index = world.resources.text_cache.add_text("New Text");
        world.set_text(entity, Text::new(text_index));

        if !world.entity_has_local_transform(entity) {
            world.set_local_transform(entity, LocalTransform::default());
        }
        if !world.entity_has_global_transform(entity) {
            world.set_global_transform(entity, GlobalTransform::default());
        }
        if !world.entity_has_local_transform_dirty(entity) {
            world.set_local_transform_dirty(entity, LocalTransformDirty);
        }
        if world.get_visibility(entity).is_none() {
            world.set_visibility(entity, Visibility { visible: true });
        }
    }

    fn remove_component(&self, world: &mut World, entity: Entity) {
        if let Some(text) = world.get_text(entity) {
            world.resources.text_cache.remove_text(text.text_index);
        }
        world.remove_text(entity);
    }

    fn ui(
        &mut self,
        world: &mut World,
        entity: Entity,
        ui: &mut egui::Ui,
        _editor: &mut EditorContext,
    ) {
        ui.label("Text");

        let (text_index, current_content) = if let Some(text) = world.get_text(entity) {
            let content = world
                .resources
                .text_cache
                .get_text(text.text_index)
                .map(|s| s.to_string())
                .unwrap_or_default();
            (text.text_index, content)
        } else {
            return;
        };

        let mut text_content = current_content.clone();
        ui.horizontal(|ui| {
            ui.label("Content:");
            ui.text_edit_multiline(&mut text_content)
        });

        if text_content != current_content {
            world
                .resources
                .text_cache
                .set_text(text_index, text_content);
            if let Some(text) = world.get_text_mut(entity) {
                text.dirty = true;
            }
        }

        let number_of_fonts = world.resources.text_cache.font_manager.fonts.len();
        if let Some(text) = world.get_text_mut(entity) {
            let mut changed = false;

            ui.separator();

            ui.horizontal(|ui| {
                ui.label("Font Size:");
                if ui
                    .add(
                        egui::DragValue::new(&mut text.properties.font_size)
                            .speed(0.5)
                            .range(1.0..=200.0),
                    )
                    .changed()
                {
                    changed = true;
                }
            });

            ui.horizontal(|ui| {
                ui.label("Color:");
                let mut color = [
                    text.properties.color.x,
                    text.properties.color.y,
                    text.properties.color.z,
                    text.properties.color.w,
                ];
                if ui.color_edit_button_rgba_unmultiplied(&mut color).changed() {
                    text.properties.color =
                        nalgebra_glm::vec4(color[0], color[1], color[2], color[3]);
                    changed = true;
                }
            });

            ui.horizontal(|ui| {
                ui.label("Alignment:");
                egui::ComboBox::from_label("")
                    .selected_text(format!("{:?}", text.properties.alignment))
                    .show_ui(ui, |ui| {
                        if ui
                            .selectable_value(
                                &mut text.properties.alignment,
                                TextAlignment::Left,
                                "Left",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                        if ui
                            .selectable_value(
                                &mut text.properties.alignment,
                                TextAlignment::Center,
                                "Center",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                        if ui
                            .selectable_value(
                                &mut text.properties.alignment,
                                TextAlignment::Right,
                                "Right",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                    });
            });

            ui.horizontal(|ui| {
                ui.label("V-Align:");
                egui::ComboBox::from_label("v_align")
                    .selected_text(format!("{:?}", text.properties.vertical_alignment))
                    .show_ui(ui, |ui| {
                        if ui
                            .selectable_value(
                                &mut text.properties.vertical_alignment,
                                VerticalAlignment::Top,
                                "Top",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                        if ui
                            .selectable_value(
                                &mut text.properties.vertical_alignment,
                                VerticalAlignment::Middle,
                                "Middle",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                        if ui
                            .selectable_value(
                                &mut text.properties.vertical_alignment,
                                VerticalAlignment::Bottom,
                                "Bottom",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                        if ui
                            .selectable_value(
                                &mut text.properties.vertical_alignment,
                                VerticalAlignment::Baseline,
                                "Baseline",
                            )
                            .changed()
                        {
                            changed = true;
                        }
                    });
            });

            ui.horizontal(|ui| {
                ui.label("Line Height:");
                if ui
                    .add(
                        egui::DragValue::new(&mut text.properties.line_height)
                            .speed(0.01)
                            .range(0.5..=3.0),
                    )
                    .changed()
                {
                    changed = true;
                }
            });

            ui.horizontal(|ui| {
                ui.label("Letter Spacing:");
                if ui
                    .add(
                        egui::DragValue::new(&mut text.properties.letter_spacing)
                            .speed(0.1)
                            .range(-10.0..=50.0),
                    )
                    .changed()
                {
                    changed = true;
                }
            });

            ui.separator();
            ui.label("Outline");

            ui.horizontal(|ui| {
                ui.label("Width:");
                if ui
                    .add(
                        egui::DragValue::new(&mut text.properties.outline_width)
                            .speed(0.001)
                            .range(0.0..=0.5),
                    )
                    .changed()
                {
                    changed = true;
                }
            });

            ui.horizontal(|ui| {
                ui.label("Color:");
                let mut outline_color = [
                    text.properties.outline_color.x,
                    text.properties.outline_color.y,
                    text.properties.outline_color.z,
                    text.properties.outline_color.w,
                ];
                if ui
                    .color_edit_button_rgba_unmultiplied(&mut outline_color)
                    .changed()
                {
                    text.properties.outline_color = nalgebra_glm::vec4(
                        outline_color[0],
                        outline_color[1],
                        outline_color[2],
                        outline_color[3],
                    );
                    changed = true;
                }
            });

            ui.horizontal(|ui| {
                ui.label("Smoothing:");
                if ui
                    .add(
                        egui::DragValue::new(&mut text.properties.smoothing)
                            .speed(0.001)
                            .range(0.001..=0.1),
                    )
                    .changed()
                {
                    changed = true;
                }
            });

            ui.separator();

            ui.horizontal(|ui| {
                ui.label("Font:");
                egui::ComboBox::from_label("font_select")
                    .selected_text(format!("Font {}", text.font_index))
                    .show_ui(ui, |ui| {
                        for i in 0..number_of_fonts {
                            if ui
                                .selectable_value(&mut text.font_index, i, format!("Font {}", i))
                                .changed()
                            {
                                changed = true;
                            }
                        }
                    });
            });

            if changed {
                text.dirty = true;
            }
        }
    }
}
