//! Palette definition and color mixing utilities.

use ratatui::style::Color;

/// RGB color triple.
pub type Rgb = (u8, u8, u8);

/// Base color palette that themes are derived from.
pub struct Palette {
    // Core
    pub bg: Rgb,
    pub surface: Rgb,
    pub surface2: Rgb,
    pub fg: Rgb,
    pub fg_dim: Rgb,
    pub fg_muted: Rgb,
    // Semantic accents
    pub accent: Rgb,
    pub red: Rgb,
    pub green: Rgb,
    pub yellow: Rgb,
    pub blue: Rgb,
    pub purple: Rgb,
    pub cyan: Rgb,
    pub orange: Rgb,
    // Role assignments
    pub tempo_color: Rgb,
    pub bank_color: Rgb,
    pub pattern_color: Rgb,
    pub title_accent: Rgb,
    pub title_author: Rgb,
    pub secondary: Rgb,
    // Arrays
    pub link_bright: [Rgb; 5],
    pub link_dim: [Rgb; 5],
    pub sparkle: [Rgb; 5],
    pub meter: [Rgb; 3],
}

/// Convert an RGB triple to a ratatui [`Color`].
pub fn rgb(c: Rgb) -> Color {
    Color::Rgb(c.0, c.1, c.2)
}

/// Blend `bg` toward `accent` by `amount` (0.0–1.0).
pub fn tint(bg: Rgb, accent: Rgb, amount: f32) -> Rgb {
    let mix = |b: u8, a: u8| -> u8 {
        let v = b as f32 + (a as f32 - b as f32) * amount;
        v.clamp(0.0, 255.0) as u8
    };
    (mix(bg.0, accent.0), mix(bg.1, accent.1), mix(bg.2, accent.2))
}

/// Linearly interpolate between two colors.
pub fn mid(a: Rgb, b: Rgb, t: f32) -> Rgb {
    tint(a, b, t)
}

/// Darken a color by reducing brightness.
pub fn darken(c: Rgb, amount: f32) -> Rgb {
    let d = |v: u8| -> u8 { (v as f32 * (1.0 - amount)).clamp(0.0, 255.0) as u8 };
    (d(c.0), d(c.1), d(c.2))
}
