// Probe: console band meter. Thin client of the shared pipeline.
//
//   cargo run --bin audio-visualizer -- [<index> | monitor | loopback | <file>]
//   cargo run --bin audio-visualizer -- --list
//
// Levels are AGC-normalised 0..1. `*` flashes on a band onset (transient).
// Ctrl-C terminates (probe tool, no graceful handler).

use std::io::Write;
use std::thread;
use std::time::Duration;

use audio_visualizer::audio::{self, Source};

fn main() -> anyhow::Result<()> {
    let args: Vec<String> = std::env::args().collect();
    if args.iter().any(|a| a == "--list") {
        return audio::print_devices();
    }
    audio::print_devices()?;

    let src = match args.get(1).map(|s| s.as_str()) {
        None => Source::Capture(None),
        Some("monitor") => Source::CaptureNamed("monitor".into()),
        Some("loopback") => Source::CaptureNamed("loopback".into()),
        Some(a) => match a.parse::<usize>() {
            Ok(i) => Source::Capture(Some(i)),
            Err(_) => Source::File(a.into()),
        },
    };

    let mut handle = audio::start(src)?;
    eprintln!("(capture: route the sink monitor in via pavucontrol Recording tab)\n");

    loop {
        let b = handle.bands();
        print!(
            "\rLOW {}{} MID {}{} HIGH {}{}  ",
            bar(b.low),
            hit(b.low_on),
            bar(b.mid),
            hit(b.mid_on),
            bar(b.high),
            hit(b.high_on),
        );
        let _ = std::io::stdout().flush();
        thread::sleep(Duration::from_millis(16));
    }
}

// 20-cell linear meter on already-normalised input.
fn bar(v: f32) -> String {
    let fill = (v.clamp(0.0, 1.0) * 20.0) as usize;
    format!("[{}{}]", "#".repeat(fill), " ".repeat(20 - fill))
}

fn hit(on: f32) -> &'static str {
    if on > 0.5 { "*" } else { " " }
}
