use {
    crate::{scale::Scale, state::State, text::TextTexture, theme::Color, tree::NodeId},
    std::{
        cell::{Cell, RefCell},
        rc::Rc,
    },
};

/// A single entry (tab) within a tab bar.
pub struct TabBarEntry {
    /// The node ID of the child this tab represents.
    pub child_id: NodeId,
    /// The display title of the tab.
    pub title: String,
    /// Pre-rendered text texture for the tab title.
    pub title_texture: Rc<RefCell<Option<TextTexture>>>,
    /// Whether this is the active (visible) tab.
    pub active: bool,
    /// Whether this tab's window has requested attention.
    pub attention_requested: bool,
    /// X offset of this tab within the tab bar (relative to tab bar start).
    pub x: Cell<i32>,
    /// Width of this tab in pixels.
    pub width: Cell<i32>,
}

/// A tab bar rendered above a container in mono (tabbed) mode.
pub struct TabBar {
    /// The individual tab entries.
    pub entries: Vec<TabBarEntry>,
    /// Height of the tab bar in pixels (from theme).
    pub height: i32,
    /// The output scale at which text textures were rendered.
    pub render_scale: Scale,
}

impl TabBar {
    /// Create a new empty tab bar.
    pub fn new(height: i32, render_scale: Scale) -> Self {
        Self {
            entries: Vec::new(),
            height,
            render_scale,
        }
    }

    /// Recompute the positions and widths of all tab entries.
    ///
    /// `total_width` is the available width for the entire tab bar.
    pub fn layout_entries(&self, total_width: i32, padding: i32) {
        let n = self.entries.len() as i32;
        if n == 0 {
            return;
        }
        let total_padding = padding * (n + 1);
        let available = (total_width - total_padding).max(0);
        let per_tab = available / n;
        let mut remainder = available - per_tab * n;
        let mut x = padding;
        for entry in &self.entries {
            let w = if remainder > 0 {
                remainder -= 1;
                per_tab + 1
            } else {
                per_tab
            };
            entry.x.set(x);
            entry.width.set(w);
            x += w + padding;
        }
    }

    /// Find the tab entry index at the given x coordinate (relative to tab bar).
    ///
    /// Returns `None` if the coordinate is in padding between tabs or out of bounds.
    pub fn entry_at_x(&self, x: i32) -> Option<usize> {
        for (i, entry) in self.entries.iter().enumerate() {
            let ex = entry.x.get();
            let ew = entry.width.get();
            if x >= ex && x < ex + ew {
                return Some(i);
            }
        }
        None
    }

    /// Get the colors for a tab entry based on its state.
    pub fn entry_colors(state: &State, entry: &TabBarEntry) -> (Color, Color, Color) {
        let theme = &state.theme;
        if entry.attention_requested {
            (
                theme.colors.tab_attention_background.get(),
                theme.colors.tab_inactive_border.get(),
                theme.colors.tab_active_text.get(),
            )
        } else if entry.active {
            (
                theme.colors.tab_active_background.get(),
                theme.colors.tab_active_border.get(),
                theme.colors.tab_active_text.get(),
            )
        } else {
            (
                theme.colors.tab_inactive_background.get(),
                theme.colors.tab_inactive_border.get(),
                theme.colors.tab_inactive_text.get(),
            )
        }
    }
}
