//! Render the metronome UI (pm-ui) for a real parsed track onto a 320×480 framebuffer and save a
//! PNG — no device. `cargo run` [program-string]. Lets the UI be developed/reviewed off the bench.

use embedded_graphics::{pixelcolor::Rgb565, prelude::*};
use pm_ui::{LaneView, Screen};

const W: u32 = 320;
const H: u32 = 480;

struct Fb {
    px: Vec<Rgb565>,
}
impl Fb {
    fn new() -> Self {
        Fb { px: vec![Rgb565::BLACK; (W * H) as usize] }
    }
}
impl DrawTarget for Fb {
    type Color = Rgb565;
    type Error = core::convert::Infallible;
    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
    where
        I: IntoIterator<Item = Pixel<Self::Color>>,
    {
        for Pixel(p, c) in pixels {
            if p.x >= 0 && p.y >= 0 && (p.x as u32) < W && (p.y as u32) < H {
                self.px[(p.y as u32 * W + p.x as u32) as usize] = c;
            }
        }
        Ok(())
    }
}
impl OriginDimensions for Fb {
    fn size(&self) -> Size {
        Size::new(W, H)
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let prog = args
        .get(1)
        .cloned()
        .unwrap_or_else(|| "t128;kick:4=Xxxx;snare:4=.x.x;hatClosed:4/2;ride:4/2s=X.x.x.x.;cowbell:3~".into());

    let track = track_format::parse(&prog);
    let lanes: Vec<LaneView> = track
        .lanes
        .iter()
        .map(|l| LaneView {
            name: &l.sound,
            levels: &l.levels,
            orns: &l.orns,
            groups: &l.groups,
            beats: l.groups.iter().sum::<u32>().min(255) as u8,
            poly: l.poly,
            muted: l.mute,
        })
        .collect();
    let screen = Screen {
        name: "Four-on-the-floor",
        bpm: track.bpm,
        playing: true,
        phase: 0.30,
        lanes: &lanes,
    };

    let mut fb = Fb::new();
    pm_ui::draw_metronome(&mut fb, &screen).unwrap();

    let img = image::RgbImage::from_fn(W, H, |x, y| {
        let c = fb.px[(y * W + x) as usize];
        let r = (c.r() << 3) | (c.r() >> 2);
        let g = (c.g() << 2) | (c.g() >> 4);
        let b = (c.b() << 3) | (c.b() >> 2);
        image::Rgb([r, g, b])
    });
    let out = "pm-kit-ui.png";
    img.save(out).unwrap();
    println!("wrote {out} ({W}x{H}) for: {prog}");
}
