use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::text::components::{TextAlignment, VerticalAlignment};
use crate::ecs::tween::easing::EasingFunction;
use crate::ecs::ui::components::{
    AutoSizeMode, DragPayload, StateTransition, ThemeColor, UiAnimationPhase, UiAnimationType,
    UiDepthMode, UiDragSource, UiDropTarget, UiLayoutNode, UiLayoutRoot, UiNodeAnimation,
    UiNodeColor, UiNodeContent, UiNodeInteraction, UiStateWeights, UiThemeBinding,
};
use crate::ecs::ui::layout_types::{
    BoundaryLayout, FlowAlignment, FlowDirection, FlowLayout, GridLayout, ScalingMode, SolidLayout,
    UiLayoutType, WindowLayout,
};
use crate::ecs::ui::state::{UiBase, UiHover, UiStateTrait};
use crate::ecs::ui::theme::UiTheme;
use crate::ecs::ui::types::Anchor;
use crate::ecs::ui::units::UiValue;
use crate::ecs::world::World;
use crate::render::wgpu::passes::geometry::UiLayer;

pub struct UiTreeBuilder<'a> {
    world: &'a mut World,
    root: freecs::Entity,
    current_parent: freecs::Entity,
    parent_stack: Vec<freecs::Entity>,
    next_tab_index: i32,
}

impl<'a> UiTreeBuilder<'a> {
    pub fn new(world: &'a mut World) -> Self {
        let entities = world.spawn_entities(
            crate::ecs::world::UI_LAYOUT_ROOT | crate::ecs::world::PARENT,
            1,
        );
        let root = entities[0];

        if let Some(root_comp) = world.get_ui_layout_root_mut(root) {
            *root_comp = UiLayoutRoot::default();
        }

        world.resources.children_cache_valid = false;
        world.resources.retained_ui.layout_dirty = true;

        Self {
            world,
            root,
            current_parent: root,
            parent_stack: Vec::new(),
            next_tab_index: 0,
        }
    }

    pub fn new_for_window(world: &'a mut World, window_index: usize) -> Self {
        let entities = world.spawn_entities(
            crate::ecs::world::UI_LAYOUT_ROOT | crate::ecs::world::PARENT,
            1,
        );
        let root = entities[0];

        if let Some(root_comp) = world.get_ui_layout_root_mut(root) {
            *root_comp = UiLayoutRoot {
                target_window: Some(window_index),
                ..UiLayoutRoot::default()
            };
        }

        world.resources.children_cache_valid = false;
        world.resources.retained_ui.layout_dirty = true;

        Self {
            world,
            root,
            current_parent: root,
            parent_stack: Vec::new(),
            next_tab_index: 0,
        }
    }

    pub fn from_parent(world: &'a mut World, parent_entity: freecs::Entity) -> Self {
        world.resources.children_cache_valid = false;
        world.resources.retained_ui.layout_dirty = true;
        Self {
            world,
            root: parent_entity,
            current_parent: parent_entity,
            parent_stack: Vec::new(),
            next_tab_index: 0,
        }
    }

    pub fn finish_subtree(self) {}

    pub fn assign_tab_index(&mut self, entity: freecs::Entity) {
        if let Some(interaction) = self.world.get_ui_node_interaction_mut(entity) {
            interaction.tab_index = Some(self.next_tab_index);
        }
        self.next_tab_index += 1;
    }

    pub fn with_absolute_scale(self, scale: f32) -> Self {
        if let Some(root) = self.world.get_ui_layout_root_mut(self.root) {
            root.absolute_scale = scale;
        }
        self
    }

    pub fn with_default_font_size(self, size: f32) -> Self {
        if let Some(root) = self.world.get_ui_layout_root_mut(self.root) {
            root.default_font_size = size;
        }
        self
    }

    pub fn root_entity(&self) -> freecs::Entity {
        self.root
    }

    pub fn current_parent(&self) -> freecs::Entity {
        self.current_parent
    }

    pub fn world_mut(&mut self) -> &mut World {
        self.world
    }

    pub fn active_theme(&self) -> &UiTheme {
        self.world.resources.retained_ui.theme_state.active_theme()
    }

    pub fn add_node(&mut self) -> UiNodeBuilder<'_, 'a> {
        let entities = self.world.spawn_entities(
            crate::ecs::world::UI_LAYOUT_NODE
                | crate::ecs::world::UI_NODE_COLOR
                | crate::ecs::world::UI_NODE_CONTENT
                | crate::ecs::world::UI_STATE_WEIGHTS
                | crate::ecs::world::PARENT,
            1,
        );
        let entity = entities[0];

        if let Some(parent) = self.world.get_parent_mut(entity) {
            *parent = crate::ecs::transform::components::Parent(Some(self.current_parent));
        }
        if let Some(node) = self.world.get_ui_layout_node_mut(entity) {
            *node = UiLayoutNode::default();
        }
        if let Some(color) = self.world.get_ui_node_color_mut(entity) {
            *color = UiNodeColor::default();
        }
        if let Some(content) = self.world.get_ui_node_content_mut(entity) {
            *content = UiNodeContent::default();
        }
        if let Some(weights) = self.world.get_ui_state_weights_mut(entity) {
            *weights = UiStateWeights::default();
        }

        self.world.resources.children_cache_valid = false;
        self.world.resources.retained_ui.layout_dirty = true;

        UiNodeBuilder { tree: self, entity }
    }

    pub fn push_parent(&mut self, entity: freecs::Entity) {
        debug_assert!(
            entity != self.current_parent && !self.parent_stack.contains(&entity),
            "push_parent cycle detected: entity {:?} is already in the parent chain",
            entity
        );
        self.parent_stack.push(self.current_parent);
        self.current_parent = entity;
    }

    pub fn pop_parent(&mut self) {
        if let Some(parent) = self.parent_stack.pop() {
            self.current_parent = parent;
        }
    }

    pub fn within_content(&mut self, entity: freecs::Entity, f: impl FnOnce(&mut UiTreeBuilder)) {
        let content = self.world.ui_widget_content(entity).unwrap_or(entity);
        self.push_parent(content);
        f(self);
        self.pop_parent();
    }

    pub fn finish(self) -> freecs::Entity {
        #[cfg(debug_assertions)]
        self.validate_layout();
        self.root
    }

    #[cfg(debug_assertions)]
    fn validate_layout(&self) {
        let children: Vec<freecs::Entity> = self
            .world
            .resources
            .children_cache
            .get(&self.root)
            .map(|v| v.to_vec())
            .unwrap_or_default();

        let root_has_flow = self
            .world
            .get_ui_layout_node(self.root)
            .is_some_and(|n| n.flow_layout.is_some());

        for child in &children {
            if let Some(node) = self.world.get_ui_layout_node(*child)
                && !root_has_flow
                && let Some(ref child_size) = node.flow_child_size
            {
                let has_relative = child_size.relative.is_some()
                    || child_size.relative_width.is_some()
                    || child_size.relative_height.is_some();
                if has_relative {
                    eprintln!(
                        "UI layout warning: entity {:?} has flow_child_size with relative units but parent {:?} has no flow layout",
                        child, self.root
                    );
                }
            }
        }
    }
}

pub struct UiNodeBuilder<'b, 'a> {
    tree: &'b mut UiTreeBuilder<'a>,
    entity: freecs::Entity,
}

impl<'b, 'a> UiNodeBuilder<'b, 'a> {
    pub fn entity(&self) -> freecs::Entity {
        self.entity
    }

    pub fn boundary(
        self,
        position_1: impl Into<UiValue<Vec2>>,
        position_2: impl Into<UiValue<Vec2>>,
    ) -> Self {
        let layout = UiLayoutType::Boundary(BoundaryLayout {
            position_1: position_1.into(),
            position_2: position_2.into(),
        });
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.layouts[UiBase::INDEX] = Some(layout);
        }
        self
    }

    pub fn window(
        self,
        position: impl Into<UiValue<Vec2>>,
        size: impl Into<UiValue<Vec2>>,
        anchor: Anchor,
    ) -> Self {
        let layout = UiLayoutType::Window(WindowLayout {
            position: position.into(),
            size: size.into(),
            anchor,
        });
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.layouts[UiBase::INDEX] = Some(layout);
        }
        self
    }

    pub fn solid(
        self,
        size: impl Into<UiValue<Vec2>>,
        scaling: ScalingMode,
        alignment: Vec2,
    ) -> Self {
        let layout = UiLayoutType::Solid(SolidLayout {
            size: size.into(),
            scaling,
            alignment,
        });
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.layouts[UiBase::INDEX] = Some(layout);
        }
        self
    }

    pub fn flow(self, direction: FlowDirection, padding: f32, spacing: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.flow_layout = Some(FlowLayout {
                direction,
                padding,
                spacing,
                alignment: FlowAlignment::Start,
                cross_alignment: FlowAlignment::Start,
                wrap: false,
            });
        }
        self
    }

    pub fn flow_with_alignment(
        self,
        direction: FlowDirection,
        padding: f32,
        spacing: f32,
        alignment: FlowAlignment,
        cross_alignment: FlowAlignment,
    ) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.flow_layout = Some(FlowLayout {
                direction,
                padding,
                spacing,
                alignment,
                cross_alignment,
                wrap: false,
            });
        }
        self
    }

    pub fn flow_wrap(self) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity)
            && let Some(flow) = &mut node.flow_layout
        {
            flow.wrap = true;
        }
        self
    }

    pub fn grid(
        self,
        columns: usize,
        row_height: f32,
        padding: f32,
        column_spacing: f32,
        row_spacing: f32,
    ) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.grid_layout = Some(GridLayout {
                columns,
                row_height,
                padding,
                column_spacing,
                row_spacing,
                min_column_width: None,
            });
        }
        self
    }

    pub fn auto_grid(self, min_column_width: f32, row_height: f32, spacing: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.grid_layout = Some(GridLayout {
                columns: 1,
                row_height,
                padding: spacing,
                column_spacing: spacing,
                row_spacing: spacing,
                min_column_width: Some(min_column_width),
            });
        }
        self
    }

    pub fn flow_child(self, size: impl Into<UiValue<Vec2>>) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.flow_child_size = Some(size.into());
        }
        self
    }

    pub fn flex_grow(self, weight: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.flex_grow = Some(weight);
        }
        self
    }

    pub fn flex_shrink(self, factor: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.flex_shrink = Some(factor);
        }
        self
    }

    pub fn with_min_size(self, min: Vec2) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.min_size = Some(min);
        }
        self
    }

    pub fn with_max_size(self, max: Vec2) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.max_size = Some(max);
        }
        self
    }

    pub fn with_z_index(self, z: i32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.z_index = Some(z);
        }
        self
    }

    pub fn auto_size(self, mode: AutoSizeMode) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.auto_size = mode;
        }
        self
    }

    pub fn auto_size_padding(self, padding: Vec2) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.auto_size_padding = padding;
        }
        self
    }

    pub fn with_state_layout<S: UiStateTrait>(self, layout: UiLayoutType) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.layouts[S::INDEX] = Some(layout);
        }
        self
    }

    pub fn with_hover_layout(self, layout: UiLayoutType) -> Self {
        self.with_state_layout::<UiHover>(layout)
    }

    pub fn with_rect(self, corner_radius: f32, border_width: f32, border_color: Vec4) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity) {
            *content = UiNodeContent::Rect {
                corner_radius,
                border_width,
                border_color,
            };
        }
        self
    }

    pub fn with_text(self, text: &str, font_size: f32) -> Self {
        let text_slot = self.tree.world.resources.text_cache.add_text(text);
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity) {
            *content = UiNodeContent::Text {
                text_slot,
                font_index: 0,
                font_size_override: Some(font_size),
                outline_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                outline_width: 0.0,
                alignment: TextAlignment::Center,
                vertical_alignment: VerticalAlignment::Middle,
                overflow: crate::ecs::ui::components::TextOverflow::default(),
            };
        }
        self
    }

    pub fn with_text_slot(self, text_slot: usize, font_size: f32) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity) {
            *content = UiNodeContent::Text {
                text_slot,
                font_index: 0,
                font_size_override: Some(font_size),
                outline_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                outline_width: 0.0,
                alignment: TextAlignment::Center,
                vertical_alignment: VerticalAlignment::Middle,
                overflow: crate::ecs::ui::components::TextOverflow::default(),
            };
        }
        self
    }

    pub fn with_text_alignment(
        self,
        text_alignment: TextAlignment,
        text_vertical_alignment: VerticalAlignment,
    ) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity)
            && let UiNodeContent::Text {
                alignment,
                vertical_alignment,
                ..
            } = content
        {
            *alignment = text_alignment;
            *vertical_alignment = text_vertical_alignment;
        }
        self
    }

    pub fn with_text_outline(self, color: Vec4, width: f32) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity)
            && let UiNodeContent::Text {
                outline_color,
                outline_width,
                ..
            } = content
        {
            *outline_color = color;
            *outline_width = width;
        }
        self
    }

    pub fn with_text_overflow(self, mode: crate::ecs::ui::components::TextOverflow) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity)
            && let UiNodeContent::Text { overflow, .. } = content
        {
            *overflow = mode;
        }
        self
    }

    pub fn with_text_wrap(self) -> Self {
        self.with_text_overflow(crate::ecs::ui::components::TextOverflow::Wrap)
    }

    pub fn with_image(self, texture_index: u32) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity) {
            *content = UiNodeContent::Image {
                texture_index,
                uv_min: Vec2::new(0.0, 0.0),
                uv_max: Vec2::new(1.0, 1.0),
            };
        }
        self
    }

    pub fn with_image_uv(self, texture_index: u32, uv_min: Vec2, uv_max: Vec2) -> Self {
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity) {
            *content = UiNodeContent::Image {
                texture_index,
                uv_min,
                uv_max,
            };
        }
        self
    }

    pub fn with_color<S: UiStateTrait>(self, color: Vec4) -> Self {
        if let Some(node_color) = self.tree.world.get_ui_node_color_mut(self.entity) {
            node_color.colors[S::INDEX] = Some(color);
        }
        if let Some(binding) = self.tree.world.get_ui_theme_binding_mut(self.entity) {
            binding.color_roles[S::INDEX] = None;
        }
        self
    }

    pub fn with_theme_color<S: UiStateTrait>(self, role: ThemeColor) -> Self {
        let color = {
            let theme = self
                .tree
                .world
                .resources
                .retained_ui
                .theme_state
                .active_theme();
            role.resolve(theme)
        };
        if let Some(node_color) = self.tree.world.get_ui_node_color_mut(self.entity) {
            node_color.colors[S::INDEX] = Some(color);
        }
        if self.tree.world.get_ui_theme_binding(self.entity).is_none() {
            self.tree
                .world
                .set_ui_theme_binding(self.entity, UiThemeBinding::default());
        }
        if let Some(binding) = self.tree.world.get_ui_theme_binding_mut(self.entity) {
            binding.color_roles[S::INDEX] = Some(role);
        }
        self
    }

    pub fn with_theme_border_color(self, role: ThemeColor) -> Self {
        let color = {
            let theme = self
                .tree
                .world
                .resources
                .retained_ui
                .theme_state
                .active_theme();
            role.resolve(theme)
        };
        if let Some(content) = self.tree.world.get_ui_node_content_mut(self.entity)
            && let UiNodeContent::Rect { border_color, .. } = content
        {
            *border_color = color;
        }
        if self.tree.world.get_ui_theme_binding(self.entity).is_none() {
            self.tree
                .world
                .set_ui_theme_binding(self.entity, UiThemeBinding::default());
        }
        if let Some(binding) = self.tree.world.get_ui_theme_binding_mut(self.entity) {
            binding.border_color_role = Some(role);
        }
        self
    }

    pub fn with_interaction(self) -> Self {
        self.tree
            .world
            .set_ui_node_interaction(self.entity, UiNodeInteraction::default());
        self
    }

    pub fn with_cursor_icon(self, icon: winit::window::CursorIcon) -> Self {
        if let Some(interaction) = self.tree.world.get_ui_node_interaction_mut(self.entity) {
            interaction.cursor_icon = Some(icon);
        }
        self
    }

    pub fn with_tooltip(self, text: &str) -> Self {
        let this = if self
            .tree
            .world
            .get_ui_node_interaction(self.entity)
            .is_none()
        {
            self.with_interaction()
        } else {
            self
        };
        if let Some(interaction) = this.tree.world.get_ui_node_interaction_mut(this.entity) {
            interaction.tooltip_text = Some(text.to_string());
        }
        this
    }

    pub fn with_tooltip_entity(self, tooltip_entity: freecs::Entity) -> Self {
        let this = if self
            .tree
            .world
            .get_ui_node_interaction(self.entity)
            .is_none()
        {
            self.with_interaction()
        } else {
            self
        };
        if let Some(interaction) = this.tree.world.get_ui_node_interaction_mut(this.entity) {
            interaction.tooltip_entity = Some(tooltip_entity);
        }
        this
    }

    pub fn with_tab_index(self, index: i32) -> Self {
        if let Some(interaction) = self.tree.world.get_ui_node_interaction_mut(self.entity) {
            interaction.tab_index = Some(index);
        }
        self
    }

    pub fn with_transition<S: UiStateTrait>(self, enter_speed: f32, exit_speed: f32) -> Self {
        if let Some(weights) = self.tree.world.get_ui_state_weights_mut(self.entity) {
            weights.transitions[S::INDEX] = Some(StateTransition {
                enter_speed,
                exit_speed,
                ..Default::default()
            });
        }
        self
    }

    pub fn with_eased_transition<S: UiStateTrait>(
        self,
        enter_speed: f32,
        exit_speed: f32,
        easing: EasingFunction,
    ) -> Self {
        if let Some(weights) = self.tree.world.get_ui_state_weights_mut(self.entity) {
            weights.transitions[S::INDEX] = Some(StateTransition {
                enter_speed,
                exit_speed,
                easing,
            });
        }
        self
    }

    pub fn with_state_index_color(self, index: usize, color: Vec4) -> Self {
        let capacity = index + 1;
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.ensure_state_capacity(capacity);
        }
        if let Some(node_color) = self.tree.world.get_ui_node_color_mut(self.entity) {
            node_color.ensure_state_capacity(capacity);
            node_color.colors[index] = Some(color);
        }
        if let Some(weights) = self.tree.world.get_ui_state_weights_mut(self.entity) {
            weights.ensure_state_capacity(capacity);
        }
        if let Some(binding) = self.tree.world.get_ui_theme_binding_mut(self.entity) {
            binding.ensure_state_capacity(capacity);
        }
        self
    }

    pub fn with_state_index_transition(
        self,
        index: usize,
        enter_speed: f32,
        exit_speed: f32,
    ) -> Self {
        let capacity = index + 1;
        if let Some(weights) = self.tree.world.get_ui_state_weights_mut(self.entity) {
            weights.ensure_state_capacity(capacity);
            weights.transitions[index] = Some(StateTransition {
                enter_speed,
                exit_speed,
                ..Default::default()
            });
        }
        self
    }

    pub fn with_depth(self, depth: UiDepthMode) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.depth = depth;
        }

        self
    }

    pub fn with_font_size(self, size: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.font_size = Some(size);
        }
        self
    }

    pub fn with_clip(self) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.clip_content = true;
        }
        self
    }

    pub fn with_visible(self, visible: bool) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.visible = visible;
        }

        self
    }

    pub fn without_pointer_events(self) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.pointer_events = false;
        }
        self
    }

    pub fn with_intro(self, animation: UiAnimationType, duration: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            let anim = node.animation.get_or_insert(UiNodeAnimation {
                intro: None,
                outro: None,
                duration,
                progress: 0.0,
                phase: UiAnimationPhase::Idle,
            });
            anim.intro = Some(animation);
            anim.duration = duration;
            if node.visible {
                anim.phase = UiAnimationPhase::IntroPlaying;
                anim.progress = 0.0;
            }
        }
        self
    }

    pub fn with_outro(self, animation: UiAnimationType, duration: f32) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            let anim = node.animation.get_or_insert(UiNodeAnimation {
                intro: None,
                outro: None,
                duration,
                progress: 0.0,
                phase: UiAnimationPhase::Idle,
            });
            anim.outro = Some(animation);
            anim.duration = duration;
        }
        self
    }

    pub fn with_drag_source(self, payload: DragPayload) -> Self {
        let this = if self
            .tree
            .world
            .get_ui_node_interaction(self.entity)
            .is_none()
        {
            self.with_interaction()
        } else {
            self
        };
        this.tree
            .world
            .set_ui_drag_source(this.entity, UiDragSource { payload });
        this
    }

    pub fn with_drop_target(self) -> Self {
        let this = if self
            .tree
            .world
            .get_ui_node_interaction(self.entity)
            .is_none()
        {
            self.with_interaction()
        } else {
            self
        };
        this.tree
            .world
            .set_ui_drop_target(this.entity, UiDropTarget::default());
        this
    }

    pub fn with_filtered_drop_target(
        self,
        filter: crate::ecs::ui::components::DragAcceptFilter,
    ) -> Self {
        let this = if self
            .tree
            .world
            .get_ui_node_interaction(self.entity)
            .is_none()
        {
            self.with_interaction()
        } else {
            self
        };
        this.tree.world.set_ui_drop_target(
            this.entity,
            UiDropTarget {
                accepted: true,
                filter,
            },
        );
        this
    }

    pub fn with_layer(self, layer: UiLayer) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.layer = Some(layer);
        }
        self
    }

    pub fn with_children(self, child_builder: impl FnOnce(&mut UiTreeBuilder<'a>)) -> Self {
        let entity = self.entity;
        let tree = self.tree;
        tree.push_parent(entity);
        child_builder(tree);
        tree.pop_parent();
        UiNodeBuilder { tree, entity }
    }

    pub fn with_responsive_flow(
        self,
        max_width: f32,
        direction: crate::ecs::ui::layout_types::FlowDirection,
    ) -> Self {
        if let Some(node) = self.tree.world.get_ui_layout_node_mut(self.entity) {
            node.responsive_flow = Some(crate::ecs::ui::layout_types::ResponsiveFlowOverride {
                max_width,
                direction,
            });
        }
        self
    }

    pub fn done(self) -> freecs::Entity {
        self.entity
    }
}
