use std::collections::HashSet;

use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::text::components::{TextAlignment, VerticalAlignment};
use crate::ecs::ui::builder::UiTreeBuilder;
use crate::ecs::ui::components::*;
use crate::ecs::ui::layout_types::FlowDirection;
use crate::ecs::ui::state::{UiBase, UiHover, UiPressed};
use crate::ecs::ui::types::Anchor;
use crate::ecs::ui::units::{Ab, Rl};
use crate::render::wgpu::passes::geometry::UiLayer;

use super::date_utils::{format_month_year, populate_calendar_grid};

impl<'a> UiTreeBuilder<'a> {
    pub fn add_dropdown(&mut self, options: &[&str], initial: usize) -> freecs::Entity {
        let theme = self.active_theme();
        let font_size = theme.font_size;
        let corner_radius = theme.corner_radius;
        let border_color = theme.border_color;
        let button_height = theme.button_height;
        let accent_color = theme.accent_color;
        let bg_color = theme.input_background_color;

        let selected_text = options.get(initial).copied().unwrap_or("");
        let header_text_slot = self
            .world_mut()
            .resources
            .text
            .cache
            .add_text(selected_text);
        let arrow_slot = self.world_mut().resources.text.cache.add_text("\u{25BC}");

        let mut popup_entities = Vec::new();
        let option_strings: Vec<String> = options.iter().map(|s| s.to_string()).collect();
        let popup_height =
            (options.len() as f32 * button_height).min(crate::ecs::ui::MAX_POPUP_HEIGHT);

        let wrapper_entity = self
            .add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
            .entity();

        self.push_parent(wrapper_entity);

        let header_entity = self
            .add_node()
            .boundary(Ab(Vec2::new(0.0, 0.0)), Rl(Vec2::new(100.0, 100.0)))
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_theme_color::<UiPressed>(ThemeColor::BackgroundActive)
            .with_interaction()
            .with_transition::<UiHover>(10.0, 6.0)
            .with_transition::<UiPressed>(14.0, 8.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .flow(FlowDirection::Horizontal, 8.0, 0.0)
            .with_children(|tree| {
                tree.add_node()
                    .flow_child(Rl(Vec2::new(0.0, 100.0)))
                    .flex_grow(1.0)
                    .with_text_slot(header_text_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                tree.add_node()
                    .flow_child(Ab(Vec2::new(20.0, 0.0)) + Rl(Vec2::new(0.0, 100.0)))
                    .with_text_slot(arrow_slot, font_size * 0.8)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();
            })
            .entity();

        let popup_container_entity = self
            .add_node()
            .window(
                Rl(Vec2::new(0.0, 100.0)),
                Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, popup_height)),
                Anchor::TopLeft,
            )
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_layer(UiLayer::Popups)
            .with_depth(UiDepthMode::Set(30.0))
            .with_visible(false)
            .with_clip()
            .flow(FlowDirection::Vertical, 0.0, 0.0)
            .entity();

        self.push_parent(popup_container_entity);

        for (index, option) in options.iter().enumerate() {
            let option_slot = self.world_mut().resources.text.cache.add_text(*option);
            let is_selected = index == initial;

            let option_entity = self
                .add_node()
                .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
                .with_rect(corner_radius, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
                .color_raw::<UiBase>(if is_selected { accent_color } else { bg_color })
                .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
                .with_theme_color::<UiPressed>(ThemeColor::BackgroundActive)
                .with_interaction()
                .with_transition::<UiHover>(10.0, 6.0)
                .with_transition::<UiPressed>(14.0, 8.0)
                .with_cursor_icon(winit::window::CursorIcon::Pointer)
                .with_children(|tree| {
                    tree.add_node()
                        .boundary(
                            Ab(Vec2::new(8.0, 0.0)),
                            Ab(Vec2::new(-8.0, 0.0)) + Rl(Vec2::new(100.0, 100.0)),
                        )
                        .with_text_slot(option_slot, font_size)
                        .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                        .with_theme_color::<UiBase>(ThemeColor::Text)
                        .entity();
                })
                .entity();

            popup_entities.push(option_entity);
        }

        self.pop_parent();
        self.pop_parent();

        self.world_mut().ui.set_ui_dropdown(
            header_entity,
            UiDropdownData {
                options: option_strings,
                selected_index: initial,
                changed: false,
                open: false,
                header_text_slot,
                popup_entities,
                popup_container_entity,
                hovered_index: None,
                is_theme_dropdown: false,
                searchable: false,
                filter_text: String::new(),
                filter_input_entity: None,
                filtered_indices: Vec::new(),
            },
        );
        if let Some(interaction) = self
            .world_mut()
            .ui
            .get_ui_node_interaction_mut(header_entity)
        {
            interaction.accessible_role = Some(AccessibleRole::Dropdown);
        }
        self.assign_tab_index(header_entity);

        header_entity
    }

    pub fn add_dropdown_searchable(&mut self, options: &[&str], initial: usize) -> freecs::Entity {
        let entity = self.add_dropdown(options, initial);
        let theme = self.active_theme();
        let font_size = theme.font_size;
        let button_height = theme.button_height;
        let corner_radius = theme.corner_radius;
        let border_color = theme.border_color;
        let accent_color = theme.accent_color;

        let popup_container = {
            if let Some(data) = self.world_mut().ui.get_ui_dropdown(entity) {
                data.popup_container_entity
            } else {
                return entity;
            }
        };

        let filter_text_slot = self.world_mut().resources.text.cache.add_text("");
        let placeholder_slot = self.world_mut().resources.text.cache.add_text("Search...");

        self.push_parent(popup_container);

        let filter_entity = self
            .add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_interaction()
            .with_cursor_icon(winit::window::CursorIcon::Text)
            .with_clip()
            .entity();

        let (selection_entity, cursor_entity, placeholder_entity) =
            self.in_parent(filter_entity, |tree| {
                let selection_entity = tree
                    .add_node()
                    .window(
                        Ab(Vec2::new(8.0, 4.0)),
                        Ab(Vec2::new(0.0, button_height - 8.0)),
                        Anchor::TopLeft,
                    )
                    .with_rect(2.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
                    .color_raw::<UiBase>(Vec4::new(
                        accent_color.x,
                        accent_color.y,
                        accent_color.z,
                        0.3,
                    ))
                    .with_visible(false)
                    .entity();

                tree.add_node()
                    .boundary(
                        Ab(Vec2::new(8.0, 0.0)),
                        Ab(Vec2::new(0.0, button_height)) + Rl(Vec2::new(100.0, 0.0)),
                    )
                    .with_text_slot(filter_text_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                let placeholder_entity = tree
                    .add_node()
                    .boundary(
                        Ab(Vec2::new(8.0, 0.0)),
                        Ab(Vec2::new(0.0, button_height)) + Rl(Vec2::new(100.0, 0.0)),
                    )
                    .with_text_slot(placeholder_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::TextDisabled)
                    .entity();

                let cursor_entity = tree
                    .add_node()
                    .window(
                        Ab(Vec2::new(8.0, 4.0)),
                        Ab(Vec2::new(2.0, button_height - 8.0)),
                        Anchor::TopLeft,
                    )
                    .with_rect(1.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .with_visible(false)
                    .entity();

                (selection_entity, cursor_entity, placeholder_entity)
            });

        self.pop_parent();

        self.world_mut()
            .resources
            .transform_state
            .children_cache_valid = false;
        if let Some(children) = self
            .world_mut()
            .resources
            .transform_state
            .children_cache
            .get_mut(&popup_container)
            && let Some(pos) = children.iter().position(|e| *e == filter_entity)
        {
            children.remove(pos);
            children.insert(0, filter_entity);
        }

        let all_indices: Vec<usize> = (0..options.len()).collect();
        if let Some(data) = self.world_mut().ui.get_ui_dropdown_mut(entity) {
            data.searchable = true;
            data.filter_input_entity = Some(filter_entity);
            data.filtered_indices = all_indices;
        }

        self.world_mut().ui.set_ui_text_input(
            filter_entity,
            UiTextInputData {
                text: String::new(),
                cursor_position: 0,
                selection_start: None,
                changed: false,
                text_slot: filter_text_slot,
                cursor_entity,
                selection_entity,
                scroll_offset: 0.0,
                cursor_blink_timer: 0.0,
                placeholder_entity: Some(placeholder_entity),
                undo_stack: std::sync::Arc::new(UndoStack::new(50)),
                input_mask: crate::ecs::ui::components::InputMask::None,
                max_length: None,
                password: false,
            },
        );

        entity
    }

    pub fn add_multi_select(&mut self, options: &[&str]) -> freecs::Entity {
        let theme = self.active_theme();
        let font_size = theme.font_size;
        let corner_radius = theme.corner_radius;
        let border_color = theme.border_color;
        let button_height = theme.button_height;
        let bg_color = theme.input_background_color;

        let header_text_slot = self.world_mut().resources.text.cache.add_text("0 selected");
        let arrow_slot = self.world_mut().resources.text.cache.add_text("\u{25BC}");

        let mut popup_entities = Vec::new();
        let mut check_entities = Vec::new();
        let option_strings: Vec<String> = options.iter().map(|s| s.to_string()).collect();
        let popup_height =
            (options.len() as f32 * button_height).min(crate::ecs::ui::MAX_POPUP_HEIGHT);

        let wrapper_entity = self
            .add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
            .entity();

        self.push_parent(wrapper_entity);

        let header_entity = self
            .add_node()
            .boundary(Ab(Vec2::new(0.0, 0.0)), Rl(Vec2::new(100.0, 100.0)))
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_theme_color::<UiPressed>(ThemeColor::BackgroundActive)
            .with_interaction()
            .with_transition::<UiHover>(10.0, 6.0)
            .with_transition::<UiPressed>(14.0, 8.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .flow(FlowDirection::Horizontal, 8.0, 0.0)
            .with_children(|tree| {
                tree.add_node()
                    .flow_child(Rl(Vec2::new(0.0, 100.0)))
                    .flex_grow(1.0)
                    .with_text_slot(header_text_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                tree.add_node()
                    .flow_child(Ab(Vec2::new(20.0, 0.0)) + Rl(Vec2::new(0.0, 100.0)))
                    .with_text_slot(arrow_slot, font_size * 0.8)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();
            })
            .entity();

        let popup_container_entity = self
            .add_node()
            .window(
                Rl(Vec2::new(0.0, 100.0)),
                Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, popup_height)),
                Anchor::TopLeft,
            )
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_layer(UiLayer::Popups)
            .with_depth(UiDepthMode::Set(30.0))
            .with_visible(false)
            .flow(FlowDirection::Vertical, 0.0, 0.0)
            .entity();

        self.push_parent(popup_container_entity);

        for option in options.iter() {
            let option_slot = self.world_mut().resources.text.cache.add_text(*option);
            let check_slot = self.world_mut().resources.text.cache.add_text(" ");

            let option_entity = self
                .add_node()
                .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
                .with_rect(corner_radius, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
                .color_raw::<UiBase>(bg_color)
                .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
                .with_interaction()
                .with_transition::<UiHover>(8.0, 6.0)
                .with_cursor_icon(winit::window::CursorIcon::Pointer)
                .flow(FlowDirection::Horizontal, 4.0, 0.0)
                .entity();

            let check_entity = self.in_parent(option_entity, |tree| {
                let check_entity = tree
                    .add_node()
                    .flow_child(Ab(Vec2::new(20.0, 0.0)) + Rl(Vec2::new(0.0, 100.0)))
                    .with_text_slot(check_slot, font_size)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                tree.add_node()
                    .flow_child(Rl(Vec2::new(0.0, 100.0)))
                    .flex_grow(1.0)
                    .with_text_slot(option_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                check_entity
            });

            popup_entities.push(option_entity);
            check_entities.push(check_entity);
        }

        self.pop_parent();
        self.pop_parent();

        self.world_mut().ui.set_ui_multi_select(
            header_entity,
            UiMultiSelectData {
                options: option_strings,
                selected_indices: HashSet::new(),
                changed: false,
                open: false,
                header_text_slot,
                popup_entities,
                popup_container_entity,
                hovered_index: None,
                check_entities,
            },
        );
        self.assign_tab_index(header_entity);

        header_entity
    }

    pub fn add_date_picker(&mut self, year: i32, month: u32, day: u32) -> freecs::Entity {
        let theme = self.active_theme();
        let font_size = theme.font_size;
        let corner_radius = theme.corner_radius;
        let border_color = theme.border_color;
        let button_height = theme.button_height;
        let accent_color = theme.accent_color;

        let header_text = format!("{year:04}-{month:02}-{day:02}");
        let header_text_slot = self.world_mut().resources.text.cache.add_text(&header_text);
        let arrow_slot = self.world_mut().resources.text.cache.add_text("\u{1F4C5}");
        let month_label = format_month_year(year, month);
        let month_label_slot = self.world_mut().resources.text.cache.add_text(&month_label);

        let cell_size = 30.0;
        let grid_width = cell_size * 7.0;
        let nav_height = button_height;
        let grid_height = cell_size * 6.0;
        let popup_height = nav_height + grid_height;

        let wrapper_entity = self
            .add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
            .entity();
        self.push_parent(wrapper_entity);

        let header_entity = self
            .add_node()
            .boundary(Ab(Vec2::new(0.0, 0.0)), Rl(Vec2::new(100.0, 100.0)))
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_theme_color::<UiPressed>(ThemeColor::BackgroundActive)
            .with_interaction()
            .with_transition::<UiHover>(10.0, 6.0)
            .with_transition::<UiPressed>(14.0, 8.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .flow(FlowDirection::Horizontal, 8.0, 0.0)
            .with_children(|tree| {
                tree.add_node()
                    .flow_child(Rl(Vec2::new(0.0, 100.0)))
                    .flex_grow(1.0)
                    .with_text_slot(header_text_slot, font_size)
                    .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();

                tree.add_node()
                    .flow_child(Ab(Vec2::new(24.0, 0.0)) + Rl(Vec2::new(0.0, 100.0)))
                    .with_text_slot(arrow_slot, font_size * 0.8)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();
            })
            .entity();

        let popup_entity = self
            .add_node()
            .window(
                Rl(Vec2::new(0.0, 100.0)),
                Ab(Vec2::new(grid_width + 8.0, popup_height + 8.0)),
                Anchor::TopLeft,
            )
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::InputBackground)
            .with_layer(UiLayer::Popups)
            .with_depth(UiDepthMode::Set(30.0))
            .with_visible(false)
            .flow(FlowDirection::Vertical, 4.0, 4.0)
            .entity();

        self.push_parent(popup_entity);

        let nav_row = self
            .add_node()
            .flow_child(Ab(Vec2::new(grid_width, nav_height)))
            .flow(FlowDirection::Horizontal, 0.0, 0.0)
            .entity();
        self.push_parent(nav_row);

        let prev_slot = self.world_mut().resources.text.cache.add_text("\u{25C0}");
        let prev_month_entity = self
            .add_node()
            .flow_child(Ab(Vec2::new(cell_size, nav_height)))
            .with_rect(corner_radius, 0.0, Vec4::zeros())
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_interaction()
            .with_transition::<UiHover>(8.0, 6.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .with_children(|tree| {
                tree.add_node()
                    .boundary(Ab(Vec2::zeros()), Rl(Vec2::new(100.0, 100.0)))
                    .with_text_slot(prev_slot, font_size)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();
            })
            .entity();

        self.add_node()
            .flow_child(Rl(Vec2::new(0.0, 100.0)))
            .flex_grow(1.0)
            .with_text_slot(month_label_slot, font_size)
            .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
            .with_theme_color::<UiBase>(ThemeColor::Text)
            .entity();

        let next_slot = self.world_mut().resources.text.cache.add_text("\u{25B6}");
        let next_month_entity = self
            .add_node()
            .flow_child(Ab(Vec2::new(cell_size, nav_height)))
            .with_rect(corner_radius, 0.0, Vec4::zeros())
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_interaction()
            .with_transition::<UiHover>(8.0, 6.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .with_children(|tree| {
                tree.add_node()
                    .boundary(Ab(Vec2::zeros()), Rl(Vec2::new(100.0, 100.0)))
                    .with_text_slot(next_slot, font_size)
                    .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                    .with_theme_color::<UiBase>(ThemeColor::Text)
                    .entity();
            })
            .entity();

        self.pop_parent();

        let mut day_entities = Vec::with_capacity(42);
        let mut day_text_slots = Vec::with_capacity(42);

        let grid_entity = self
            .add_node()
            .flow_child(Ab(Vec2::new(grid_width, grid_height)))
            .flow(FlowDirection::Horizontal, 0.0, 0.0)
            .flow_wrap()
            .entity();
        self.push_parent(grid_entity);

        for _ in 0..42 {
            let slot = self.world_mut().resources.text.cache.add_text("");
            day_text_slots.push(slot);

            let cell = self
                .add_node()
                .flow_child(Ab(Vec2::new(cell_size, cell_size)))
                .with_rect(corner_radius, 0.0, Vec4::zeros())
                .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
                .with_interaction()
                .with_transition::<UiHover>(8.0, 6.0)
                .with_cursor_icon(winit::window::CursorIcon::Pointer)
                .with_children(|tree| {
                    tree.add_node()
                        .boundary(Ab(Vec2::zeros()), Rl(Vec2::new(100.0, 100.0)))
                        .with_text_slot(slot, font_size * 0.85)
                        .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
                        .with_theme_color::<UiBase>(ThemeColor::Text)
                        .entity();
                })
                .entity();
            day_entities.push(cell);
        }

        self.pop_parent();
        self.pop_parent();
        self.pop_parent();

        populate_calendar_grid(
            self.world_mut(),
            year,
            month,
            day,
            &day_text_slots,
            &day_entities,
            accent_color,
        );

        self.world_mut().ui.set_ui_date_picker(
            header_entity,
            UiDatePickerData {
                year,
                month,
                day,
                changed: false,
                open: false,
                header_text_slot,
                popup_entity,
                day_entities,
                day_text_slots,
                month_label_slot,
                prev_month_entity,
                next_month_entity,
                selected_day_entity: None,
            },
        );
        self.assign_tab_index(header_entity);

        header_entity
    }

    pub fn add_menu(&mut self, label: &str, items: &[&str]) -> freecs::Entity {
        let theme = self.active_theme();
        let font_size = theme.font_size;
        let corner_radius = theme.corner_radius;
        let button_height = theme.button_height;
        let border_color = theme.border_color;

        let label_slot = self.world_mut().resources.text.cache.add_text(label);

        let item_strings: Vec<String> = items.iter().map(|s| s.to_string()).collect();
        let popup_height =
            (items.len() as f32 * button_height).min(crate::ecs::ui::MAX_POPUP_HEIGHT);

        let menu_button = self
            .add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
            .with_rect(corner_radius, 1.0, border_color)
            .with_theme_border_color(ThemeColor::Border)
            .with_theme_color::<UiBase>(ThemeColor::Background)
            .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
            .with_interaction()
            .with_transition::<UiHover>(8.0, 6.0)
            .with_cursor_icon(winit::window::CursorIcon::Pointer)
            .entity();

        let (popup_container_entity, popup_entities) = self.in_parent(menu_button, |tree| {
            let mut popup_entities = Vec::new();

            tree.add_node()
                .with_text_slot(label_slot, font_size)
                .with_theme_color::<UiBase>(ThemeColor::Text)
                .entity();

            let popup_container_entity = tree
                .add_node()
                .window(
                    Rl(Vec2::new(0.0, 100.0)),
                    Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, popup_height)),
                    Anchor::TopLeft,
                )
                .with_rect(corner_radius, 1.0, border_color)
                .with_theme_border_color(ThemeColor::Border)
                .with_theme_color::<UiBase>(ThemeColor::Background)
                .with_layer(UiLayer::Popups)
                .with_depth(UiDepthMode::Set(30.0))
                .with_visible(false)
                .flow(FlowDirection::Vertical, 0.0, 0.0)
                .entity();

            tree.push_parent(popup_container_entity);

            for item in items {
                let item_slot = tree.world_mut().resources.text.cache.add_text(*item);

                let item_entity = tree
                    .add_node()
                    .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, button_height)))
                    .with_rect(corner_radius, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
                    .with_theme_color::<UiBase>(ThemeColor::Background)
                    .with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
                    .with_interaction()
                    .with_transition::<UiHover>(8.0, 6.0)
                    .with_cursor_icon(winit::window::CursorIcon::Pointer)
                    .with_children(|tree| {
                        tree.add_node()
                            .with_text_slot(item_slot, font_size)
                            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
                            .with_theme_color::<UiBase>(ThemeColor::Text)
                            .entity();
                    })
                    .entity();

                popup_entities.push(item_entity);
            }

            tree.pop_parent();

            (popup_container_entity, popup_entities)
        });

        self.world_mut().ui.set_ui_menu(
            menu_button,
            UiMenuData {
                items: item_strings,
                clicked_item: None,
                open: false,
                label_text_slot: label_slot,
                popup_entities,
                popup_container_entity,
            },
        );

        menu_button
    }

    pub fn add_theme_dropdown(&mut self) -> freecs::Entity {
        let preset_names: Vec<String> = self
            .world_mut()
            .resources
            .retained_ui
            .theme_state
            .presets
            .iter()
            .map(|theme| theme.name.clone())
            .collect();

        let selected = self
            .world_mut()
            .resources
            .retained_ui
            .theme_state
            .selected_preset_index;

        let labels: Vec<&str> = preset_names.iter().map(|s| s.as_str()).collect();
        let entity = self.add_dropdown_searchable(&labels, selected.unwrap_or(0));
        if let Some(data) = self.world_mut().ui.get_ui_dropdown_mut(entity) {
            data.is_theme_dropdown = true;
        }
        entity
    }
}
