//
// Visualizer backdrop. Reads `app.spectrum` (filled by audio/analysis.jai with
// a real FFT each frame) and draws a mirrored bar visualizer with a
// bass-driven background pulse.
//
// All immediate-mode quads via Simp for now. A real GLSL fragment shader is
// on the roadmap (ai/todo.md) — once that lands this becomes a fullscreen
// quad reading the spectrum + waveform as 1D textures.
//

gfx_init :: () {
    // Nothing yet.
}

gfx_draw_visualizer_background :: (w: float, h: float) {
    update_audio_analysis();
    Simp.set_shader_for_color();

    t := cast(float) app.current_time;

    // Bass = average of the lowest ~16% of bins. Drives a subtle base
    // brightness pulse so the whole screen breathes with the kick drum.
    bass: float = 0;
    bass_bins := SPECTRUM_BINS / 6;
    if bass_bins < 1  bass_bins = 1;
    for 0..bass_bins-1  bass += app.spectrum[it];
    bass /= cast(float) bass_bins;

    base := Vector4.{
        0.04 + 0.10 * bass,
        0.02 + 0.04 * bass,
        0.10 + 0.18 * bass,
        1,
    };
    Simp.immediate_quad(0, 0, w, h, base);

    // Mirrored bars from the horizontal mid-line — bass on the left, treble
    // on the right, both spreading top and bottom.
    cy := h * 0.5;
    bar_w := w / cast(float) SPECTRUM_BINS;
    max_bar := h * 0.45;

    for i: 0..SPECTRUM_BINS-1 {
        v := app.spectrum[i];
        bar_h := v * max_bar;
        x0 := cast(float) i * bar_w;
        x1 := x0 + bar_w * 0.85;

        hue := cast(float) i / cast(float) SPECTRUM_BINS;
        body := neon_color(hue, v, t);
        tip  := body;
        tip.x = min(1.0, tip.x + 0.4);
        tip.y = min(1.0, tip.y + 0.4);
        tip.z = min(1.0, tip.z + 0.4);

        // Top half (going up).
        Simp.immediate_quad(x0, cy - bar_h, x1, cy, body);
        // Bottom half (going down) — slightly shorter so the eye reads the
        // top half as primary.
        Simp.immediate_quad(x0, cy, x1, cy + bar_h * 0.85, body);

        // Bright tip cap on the top bar (the classic Winamp peak nub).
        cap_h := max_bar * 0.012;
        if bar_h > cap_h * 2 {
            Simp.immediate_quad(x0, cy - bar_h - cap_h, x1, cy - bar_h, tip);
        }
    }

    // Center mirror line — a thin neon glow across the middle for the
    // 2000s-skin vibe.
    {
        line_h := 1.5;
        line_col := Vector4.{1.0, 0.4, 0.8, 0.5 + 0.3 * bass};
        Simp.immediate_quad(0, cy - line_h * 0.5, w, cy + line_h * 0.5, line_col);
    }
}

#scope_file

neon_color :: (hue: float, intensity: float, t: float) -> Vector4 {
    // Slow hue drift over time so the color palette evolves even on
    // sustained tones.
    h := hue + t * 0.03;
    r := 0.5 + 0.5 * sin(h * 6.28318 + 0.0);
    g := 0.5 + 0.5 * sin(h * 6.28318 + 2.094);
    b := 0.5 + 0.5 * sin(h * 6.28318 + 4.188);
    a := 0.55 + 0.45 * intensity;
    boost := 0.45 + 0.55 * intensity;
    return Vector4.{r * boost, g * boost, b * boost, a};
}
