use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::text::components::TextProperties;
use crate::render::wgpu::passes::geometry::UiRect;

use super::super::types::{Rect, UiResponse};
use super::types::ImmediateUi;

impl ImmediateUi {
    pub fn label(&mut self, text: &str) {
        let font_size = self.style.font_size;
        let char_width = font_size * 0.6;
        let text_width = text.len() as f32 * char_width;
        let alloc_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(text_width, alloc_height + self.style.spacing));
        let text_y = rect.y() + (alloc_height - font_size) * 0.5;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(text, Vec2::new(rect.x(), text_y), props);
    }

    pub fn label_colored(&mut self, text: &str, color: Vec4) {
        let font_size = self.style.font_size;
        let char_width = font_size * 0.6;
        let text_width = text.len() as f32 * char_width;
        let alloc_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(text_width, alloc_height + self.style.spacing));
        let text_y = rect.y() + (alloc_height - font_size) * 0.5;

        let props = TextProperties {
            font_size,
            color,
            ..Default::default()
        };

        self.add_text(text, Vec2::new(rect.x(), text_y), props);
    }

    pub fn heading(&mut self, text: &str) {
        let font_size = self.style.font_size * 1.5;
        let char_width = font_size * 0.55;
        let text_width = text.len() as f32 * char_width;
        let text_height = font_size;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(text_width, text_height + self.style.spacing));

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            outline_width: 0.04,
            outline_color: Vec4::new(0.0, 0.0, 0.0, 1.0),
            ..Default::default()
        };

        self.add_text(text, Vec2::new(rect.x(), rect.y()), props);
    }

    pub fn button(&mut self, label: &str) -> UiResponse {
        let id = self.make_id(label);
        let font_size = self.style.font_size;
        let char_width = font_size * 0.6;
        let text_width = label.len() as f32 * char_width;
        let button_width = text_width + self.style.padding * 3.0;
        let button_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(button_width, button_height + self.style.spacing));
        let button_rect = Rect::new(rect.x(), rect.y(), button_width, button_height);

        let response = self.interact(id, button_rect);

        let bg_color = if response.active {
            self.style.background_color_active
        } else if response.hovered {
            self.style.background_color_hovered
        } else {
            self.style.background_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(button_rect.x(), button_rect.y()),
            size: button_rect.size(),
            color: bg_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let text_x = button_rect.x() + self.style.padding;
        let text_y = button_rect.y() + (button_height - font_size) * 0.5;

        let text_color = if response.hovered {
            Vec4::new(1.0, 0.95, 0.7, 1.0)
        } else {
            self.style.text_color
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(label, Vec2::new(text_x, text_y), props);

        response
    }

    pub fn slider(&mut self, id: &str, value: &mut f32, min: f32, max: f32) -> UiResponse {
        let uid = self.make_id(id);
        let slider_width = self.layout_stack.available_width().min(200.0);
        let slider_height = self.style.slider_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(slider_width, slider_height + self.style.spacing));
        let slider_rect = Rect::new(rect.x(), rect.y(), slider_width, slider_height);

        let mut response = self.interact(uid, slider_rect);

        if response.active || response.dragging {
            let normalized =
                ((self.mouse_pos.x - slider_rect.x()) / slider_rect.width()).clamp(0.0, 1.0);
            let new_value = min + normalized * (max - min);
            if (*value - new_value).abs() > 0.0001 {
                *value = new_value;
                response.changed = true;
            }
        }

        self.add_rect(UiRect {
            position: Vec2::new(slider_rect.x(), slider_rect.y()),
            size: slider_rect.size(),
            color: self.style.background_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let fill_width = ((*value - min) / (max - min)) * slider_rect.width();
        let fill_color = if response.active {
            Vec4::new(0.3, 0.6, 1.0, 1.0)
        } else if response.hovered {
            Vec4::new(0.4, 0.7, 1.0, 1.0)
        } else {
            Vec4::new(0.2, 0.5, 0.9, 1.0)
        };

        if fill_width > 0.0 {
            self.add_rect(UiRect {
                position: Vec2::new(slider_rect.x(), slider_rect.y()),
                size: Vec2::new(fill_width, slider_rect.height()),
                color: fill_color,
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }

        let font_size = self.style.font_size * 0.8;
        let value_text = format!("{:.2}", value);
        let text_x = slider_rect.center().x - value_text.len() as f32 * font_size * 0.55 * 0.5;
        let text_y = slider_rect.y() + (slider_height - font_size) * 0.5;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(&value_text, Vec2::new(text_x, text_y), props);

        response
    }

    pub fn slider_with_label(
        &mut self,
        label: &str,
        value: &mut f32,
        min: f32,
        max: f32,
    ) -> UiResponse {
        let start_cursor = self.layout_stack.cursor();
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55 + self.style.spacing;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(
            label,
            Vec2::new(start_cursor.x, start_cursor.y + 3.0),
            props,
        );

        let temp_cursor = start_cursor + Vec2::new(label_width, 0.0);
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(temp_cursor);
        }

        let response = self.slider(label, value, min, max);

        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(
                start_cursor.x,
                response.rect.max.y + self.style.spacing,
            ));
        }

        response
    }

    pub fn toggle(&mut self, id: &str, value: &mut bool) -> UiResponse {
        let uid = self.make_id(id);
        let toggle_width = 50.0;
        let toggle_height = self.style.slider_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(toggle_width, toggle_height + self.style.spacing));
        let toggle_rect = Rect::new(rect.x(), rect.y(), toggle_width, toggle_height);

        let mut response = self.interact(uid, toggle_rect);

        if response.clicked {
            *value = !*value;
            response.changed = true;
        }

        let bg_color = if *value {
            Vec4::new(0.2, 0.7, 0.3, 1.0)
        } else {
            self.style.background_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(toggle_rect.x(), toggle_rect.y()),
            size: toggle_rect.size(),
            color: bg_color,
            corner_radius: toggle_height * 0.5,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let knob_size = toggle_height - 4.0;
        let knob_x = if *value {
            toggle_rect.max.x - knob_size - 2.0
        } else {
            toggle_rect.x() + 2.0
        };
        let knob_y = toggle_rect.y() + 2.0;

        self.add_rect(UiRect {
            position: Vec2::new(knob_x, knob_y),
            size: Vec2::new(knob_size, knob_size),
            color: Vec4::new(1.0, 1.0, 1.0, 1.0),
            corner_radius: knob_size * 0.5,
            border_width: 0.0,
            border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
            clip_rect: None,
            ..Default::default()
        });

        response
    }

    pub fn toggle_with_label(&mut self, label: &str, value: &mut bool) -> UiResponse {
        let start_cursor = self.layout_stack.cursor();
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55 + self.style.spacing;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(
            label,
            Vec2::new(start_cursor.x, start_cursor.y + 3.0),
            props,
        );

        let temp_cursor = start_cursor + Vec2::new(label_width, 0.0);
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(temp_cursor);
        }

        let response = self.toggle(label, value);

        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(
                start_cursor.x,
                response.rect.max.y + self.style.spacing,
            ));
        }

        response
    }

    pub fn checkbox(&mut self, id: &str, label: &str, value: &mut bool) -> UiResponse {
        let uid = self.make_id(id);
        let checkbox_size = self.style.checkbox_size;
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55;
        let total_width = checkbox_size + self.style.spacing + label_width;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(total_width, checkbox_size + self.style.spacing));
        let checkbox_rect = Rect::new(rect.x(), rect.y(), checkbox_size, checkbox_size);

        let mut response = self.interact(uid, checkbox_rect);

        if response.clicked {
            *value = !*value;
            response.changed = true;
        }

        let bg_color = if response.active {
            self.style.background_color_active
        } else if response.hovered {
            self.style.background_color_hovered
        } else {
            self.style.background_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(checkbox_rect.x(), checkbox_rect.y()),
            size: checkbox_rect.size(),
            color: bg_color,
            corner_radius: self.style.corner_radius * 0.5,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        if *value {
            let inner_size = checkbox_size - 8.0;
            let inner_x = checkbox_rect.x() + 4.0;
            let inner_y = checkbox_rect.y() + 4.0;

            self.add_rect(UiRect {
                position: Vec2::new(inner_x, inner_y),
                size: Vec2::new(inner_size, inner_size),
                color: Vec4::new(0.2, 0.7, 0.3, 1.0),
                corner_radius: self.style.corner_radius * 0.3,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }

        let text_x = checkbox_rect.max.x + self.style.spacing;
        let text_y = checkbox_rect.y() + (checkbox_size - font_size) * 0.5;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(label, Vec2::new(text_x, text_y), props);

        response
    }

    pub fn text_input(&mut self, id: &str, text: &mut String) -> UiResponse {
        let uid = self.make_id(id);
        let font_size = self.style.font_size;
        let input_width = self.layout_stack.available_width().min(200.0);
        let input_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(input_width, input_height + self.style.spacing));
        let input_rect = Rect::new(rect.x(), rect.y(), input_width, input_height);

        let mut response = self.interact(uid, input_rect);

        if response.clicked {
            self.focused_widget = Some(uid);
        }

        let is_focused = self.focused_widget == Some(uid);

        if is_focused {
            for character in &self.char_input.clone() {
                if !character.is_control() {
                    text.push(*character);
                    response.changed = true;
                }
            }

            for key_input in &self.key_input.clone() {
                if key_input.pressed {
                    match key_input.key {
                        winit::keyboard::KeyCode::Backspace => {
                            text.pop();
                            response.changed = true;
                        }
                        winit::keyboard::KeyCode::Escape | winit::keyboard::KeyCode::Enter => {
                            self.focused_widget = None;
                        }
                        _ => {}
                    }
                }
            }
        }

        let bg_color = if is_focused {
            Vec4::new(0.1, 0.1, 0.1, 1.0)
        } else if response.hovered {
            self.style.background_color_hovered
        } else {
            self.style.background_color
        };

        let border_color = if is_focused {
            Vec4::new(0.3, 0.6, 1.0, 1.0)
        } else {
            self.style.border_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(input_rect.x(), input_rect.y()),
            size: input_rect.size(),
            color: bg_color,
            corner_radius: self.style.corner_radius,
            border_width: if is_focused {
                2.0
            } else {
                self.style.border_width
            },
            border_color,
            clip_rect: None,
            ..Default::default()
        });

        let display_text = if text.is_empty() && !is_focused {
            "...".to_string()
        } else if is_focused {
            format!("{}|", text)
        } else {
            text.clone()
        };

        let text_x = input_rect.x() + self.style.padding;
        let text_y = input_rect.y() + (input_height - font_size) * 0.5;

        let text_color = if text.is_empty() && !is_focused {
            self.style.text_color_disabled
        } else {
            self.style.text_color
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(&display_text, Vec2::new(text_x, text_y), props);

        response
    }

    pub fn text_input_with_label(&mut self, label: &str, text: &mut String) -> UiResponse {
        let start_cursor = self.layout_stack.cursor();
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55 + self.style.spacing;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(
            label,
            Vec2::new(start_cursor.x, start_cursor.y + 7.0),
            props,
        );

        let temp_cursor = start_cursor + Vec2::new(label_width, 0.0);
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(temp_cursor);
        }

        let response = self.text_input(label, text);

        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(
                start_cursor.x,
                response.rect.max.y + self.style.spacing,
            ));
        }

        response
    }

    pub fn collapsing_header(&mut self, label: &str, default_open: bool) -> bool {
        let uid = self.make_id(label);
        let font_size = self.style.font_size;
        let header_height = self.style.button_height;

        let width = self.layout_stack.available_width();
        let rect = self
            .layout_stack
            .allocate(Vec2::new(width, header_height + self.style.spacing));
        let header_rect = Rect::new(rect.x(), rect.y(), width, header_height);

        let state = self.get_state(uid);
        let is_open = if state.panel_position.is_none() {
            let mut new_state = state;
            new_state.panel_position = Some(Vec2::new(if default_open { 1.0 } else { 0.0 }, 0.0));
            new_state.collapsed = !default_open;
            self.set_state(uid, new_state);
            default_open
        } else {
            !state.collapsed
        };

        let response = self.interact(uid, header_rect);

        if response.clicked {
            let mut new_state = self.get_state(uid);
            new_state.collapsed = is_open;
            self.set_state(uid, new_state);
        }

        let bg_color = if response.active {
            self.style.background_color_active
        } else if response.hovered {
            self.style.background_color_hovered
        } else {
            Vec4::new(0.0, 0.0, 0.0, 0.0)
        };

        if bg_color.w > 0.0 {
            self.add_rect(UiRect {
                position: header_rect.min,
                size: header_rect.size(),
                color: bg_color,
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }

        let arrow = if is_open { "v" } else { ">" };
        let arrow_x = header_rect.x() + self.style.padding;
        let arrow_y = header_rect.y() + (header_height - font_size) * 0.5;

        self.add_text(
            arrow,
            Vec2::new(arrow_x, arrow_y),
            TextProperties {
                font_size,
                color: self.style.text_color,
                ..Default::default()
            },
        );

        let text_x = arrow_x + font_size;
        let text_y = header_rect.y() + (header_height - font_size) * 0.5;

        self.add_text(
            label,
            Vec2::new(text_x, text_y),
            TextProperties {
                font_size,
                color: self.style.text_color,
                ..Default::default()
            },
        );

        !self.get_state(uid).collapsed
    }

    pub fn radio_value<T: PartialEq + Copy>(
        &mut self,
        label: &str,
        current: &mut T,
        value: T,
    ) -> bool {
        let uid = self.make_id(label);
        let font_size = self.style.font_size;
        let radio_size = self.style.checkbox_size;

        let label_width = label.len() as f32 * font_size * 0.55;
        let total_width = radio_size + self.style.spacing + label_width;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(total_width, radio_size + self.style.spacing));
        let radio_rect = Rect::new(rect.x(), rect.y(), radio_size, radio_size);

        let response = self.interact(uid, Rect::new(rect.x(), rect.y(), total_width, radio_size));
        let is_selected = *current == value;

        if response.clicked {
            *current = value;
        }

        let outer_color = if response.hovered {
            Vec4::new(0.5, 0.5, 0.55, 1.0)
        } else {
            self.style.border_color
        };

        self.add_rect(UiRect {
            position: radio_rect.min,
            size: radio_rect.size(),
            color: self.style.background_color,
            corner_radius: radio_size * 0.5,
            border_width: 2.0,
            border_color: outer_color,
            clip_rect: None,
            ..Default::default()
        });

        if is_selected {
            let inner_size = radio_size * 0.5;
            let inner_offset = (radio_size - inner_size) * 0.5;
            self.add_rect(UiRect {
                position: Vec2::new(radio_rect.x() + inner_offset, radio_rect.y() + inner_offset),
                size: Vec2::new(inner_size, inner_size),
                color: Vec4::new(0.3, 0.7, 1.0, 1.0),
                corner_radius: inner_size * 0.5,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }

        let text_x = radio_rect.max.x + self.style.spacing;
        let text_y = radio_rect.y() + (radio_size - font_size) * 0.5;

        let text_color = if response.hovered {
            Vec4::new(1.0, 1.0, 1.0, 1.0)
        } else {
            self.style.text_color
        };

        self.add_text(
            label,
            Vec2::new(text_x, text_y),
            TextProperties {
                font_size,
                color: text_color,
                ..Default::default()
            },
        );

        response.clicked
    }

    pub fn button_with_color(&mut self, label: &str, bg_color: Vec4) -> UiResponse {
        let id = self.make_id(label);
        let font_size = self.style.font_size;
        let char_width = font_size * 0.6;
        let text_width = label.len() as f32 * char_width;
        let button_width = text_width + self.style.padding * 3.0;
        let button_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(button_width, button_height + self.style.spacing));
        let button_rect = Rect::new(rect.x(), rect.y(), button_width, button_height);

        let response = self.interact(id, button_rect);

        let final_color = if response.active {
            Vec4::new(
                (bg_color.x * 0.8).min(1.0),
                (bg_color.y * 0.8).min(1.0),
                (bg_color.z * 0.8).min(1.0),
                bg_color.w,
            )
        } else if response.hovered {
            Vec4::new(
                (bg_color.x * 1.2).min(1.0),
                (bg_color.y * 1.2).min(1.0),
                (bg_color.z * 1.2).min(1.0),
                bg_color.w,
            )
        } else {
            bg_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(button_rect.x(), button_rect.y()),
            size: button_rect.size(),
            color: final_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let text_x = button_rect.x() + self.style.padding;
        let text_y = button_rect.y() + (button_height - font_size) * 0.5;

        let luminance = bg_color.x * 0.299 + bg_color.y * 0.587 + bg_color.z * 0.114;
        let text_color = if luminance > 0.5 {
            Vec4::new(0.0, 0.0, 0.0, 1.0)
        } else {
            Vec4::new(1.0, 1.0, 1.0, 1.0)
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(label, Vec2::new(text_x, text_y), props);

        response
    }

    pub fn draw_rect(&mut self, position: Vec2, size: Vec2, color: Vec4) {
        self.add_rect(UiRect {
            position,
            size,
            color,
            corner_radius: 0.0,
            border_width: 0.0,
            border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
            clip_rect: None,
            ..Default::default()
        });
    }

    pub fn color_picker(&mut self, id: &str, color: &mut Vec4) -> UiResponse {
        self.push_id(id);

        let start_cursor = self.layout_stack.cursor();
        let mut any_changed = false;

        let swatch_size = 30.0;
        let rect = self
            .layout_stack
            .allocate(Vec2::new(swatch_size, swatch_size + self.style.spacing));

        self.add_rect(UiRect {
            position: Vec2::new(rect.x(), rect.y()),
            size: Vec2::new(swatch_size, swatch_size),
            color: *color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let slider_start = rect.x() + swatch_size + self.style.spacing;
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(slider_start, start_cursor.y));
        }

        if self.slider("r", &mut color.x, 0.0, 1.0).changed {
            any_changed = true;
        }
        let cursor_y = self.layout_stack.cursor().y;
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(slider_start, cursor_y));
        }
        if self.slider("g", &mut color.y, 0.0, 1.0).changed {
            any_changed = true;
        }
        let cursor_y = self.layout_stack.cursor().y;
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(slider_start, cursor_y));
        }
        if self.slider("b", &mut color.z, 0.0, 1.0).changed {
            any_changed = true;
        }

        self.pop_id();

        let mut response = UiResponse::none(self.make_id(id), rect);
        response.changed = any_changed;
        response
    }

    pub fn progress_bar(&mut self, value: f32, width: f32) {
        let height = self.style.slider_height;
        let rect = self
            .layout_stack
            .allocate(Vec2::new(width, height + self.style.spacing));
        let bar_rect = Rect::new(rect.x(), rect.y(), width, height);

        self.add_rect(UiRect {
            position: Vec2::new(bar_rect.x(), bar_rect.y()),
            size: bar_rect.size(),
            color: self.style.background_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let fill_width = value.clamp(0.0, 1.0) * bar_rect.width();
        if fill_width > 0.0 {
            self.add_rect(UiRect {
                position: Vec2::new(bar_rect.x(), bar_rect.y()),
                size: Vec2::new(fill_width, bar_rect.height()),
                color: Vec4::new(0.2, 0.7, 0.3, 1.0),
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }
    }

    pub fn progress_bar_colored(&mut self, value: f32, width: f32, fill_color: Vec4) {
        let height = self.style.slider_height;
        let rect = self
            .layout_stack
            .allocate(Vec2::new(width, height + self.style.spacing));
        let bar_rect = Rect::new(rect.x(), rect.y(), width, height);

        self.add_rect(UiRect {
            position: Vec2::new(bar_rect.x(), bar_rect.y()),
            size: bar_rect.size(),
            color: self.style.background_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let fill_width = value.clamp(0.0, 1.0) * bar_rect.width();
        if fill_width > 0.0 {
            self.add_rect(UiRect {
                position: Vec2::new(bar_rect.x(), bar_rect.y()),
                size: Vec2::new(fill_width, bar_rect.height()),
                color: fill_color,
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }
    }
}
