use gtk4::prelude::*;
use gtk4::DrawingArea;
use std::sync::Arc;

use crate::processor::AtomicF32;

const METER_W: i32 = 16;
const METER_H: i32 = 120;

// Segmentos del vúmetro: (umbral 0..1, R, G, B)
const SEGMENTS: &[(f32, f64, f64, f64)] = &[
    (0.75, 0.0,  0.87, 0.25),   // verde
    (0.88, 0.89, 0.78, 0.0 ),   // amarillo
    (0.95, 0.91, 0.42, 0.02),   // naranja
    (1.0,  0.88, 0.07, 0.04),   // rojo
];

/// Vúmetro LED vertical. `value` es un AtomicF32 en rango 0..1.
#[derive(Clone)]
pub struct Meter {
    pub widget: DrawingArea,
}

impl Meter {
    /// Meter de nivel (fondo oscuro, verde→rojo de abajo a arriba)
    pub fn new_level(value: Arc<AtomicF32>) -> Self {
        Self::build(value, false)
    }

    /// Meter de gain reduction (fondo oscuro, azul de arriba a abajo)
    pub fn new_gr(value: Arc<AtomicF32>) -> Self {
        Self::build(value, true)
    }

    fn build(value: Arc<AtomicF32>, is_gr: bool) -> Self {
        let da = DrawingArea::builder()
            .width_request(METER_W)
            .height_request(METER_H)
            .build();

        da.set_draw_func(move |_da, cr, _w, h| {
            let v = value.load().clamp(0.0, 1.0) as f64;
            draw_meter(cr, h, v, is_gr);
        });

        Self { widget: da }
    }
}

fn draw_meter(cr: &cairo::Context, h: i32, value: f64, is_gr: bool) {
    let w    = METER_W as f64;
    let hf   = h as f64;
    let nseg = 30usize;
    let seg_h = hf / nseg as f64;
    let gap   = 1.5;

    let lit_count = (value * nseg as f64).round() as usize;

    for i in 0..nseg {
        // El segmento 0 está abajo; nseg-1 arriba
        let seg_idx = if is_gr { nseg - 1 - i } else { i };
        let y = hf - (i + 1) as f64 * seg_h + gap * 0.5;
        let sh = seg_h - gap;

        let lit = if is_gr {
            // GR: de arriba hacia abajo
            i >= nseg - lit_count
        } else {
            // Nivel: de abajo hacia arriba
            i < lit_count
        };

        // Color según posición del segmento (no del valor actual)
        let frac = seg_idx as f64 / nseg as f64;
        let (r, g, b) = color_for_frac(frac, is_gr);

        if lit {
            cr.set_source_rgb(r, g, b);
        } else {
            // Segmento apagado: versión muy oscura del color
            cr.set_source_rgb(r * 0.12, g * 0.12, b * 0.12);
        }

        cr.rectangle(1.5, y, w - 3.0, sh);
        let _ = cr.fill();
    }
}

fn color_for_frac(frac: f64, is_gr: bool) -> (f64, f64, f64) {
    if is_gr {
        // GR: azul siempre
        return (0.25, 0.45, 1.0);
    }
    for &(thr, r, g, b) in SEGMENTS {
        if frac <= thr as f64 {
            return (r, g, b);
        }
    }
    (0.88, 0.07, 0.04)
}
