//! fps_text: your own font, live numbers, one draw call (v0.2 step 11,
//! milestone 2).
//!
//! An FPS counter drawn with the built-in 8x8 bitmap font, updating live
//! from GameTime, over a small animated scene. The whole HUD string is ONE
//! draw call (all glyphs share the font texture; the batcher makes the
//! string a single run), so the frame totals two: the scene's white-texture
//! run and the font's run. Watch the backend's once-a-second log prove it.
//!
//! Run: RUST_LOG=info cargo run --example fps_text

use mawida::math::Vec2;
use mawida::{
    draw_text, run, AppConfig, Camera, Color, Context, Game, GameTime, MonoFont,
    OrthographicCamera, Result, Sprite,
};

struct FpsDemo {
    font: Option<MonoFont>,
    text: String,
    acc: f32,
    frames: u32,
    orbiters: Vec<Sprite>,
    camera: OrthographicCamera,
}

impl Game for FpsDemo {
    fn init(&mut self, ctx: &mut Context) -> Result<()> {
        // Build the built-in font atlas and upload it: two lines, no files.
        let font = MonoFont::builtin(ctx.content_mut());
        ctx.upload_texture(font.sheet.texture)?;
        self.font = Some(font);
        Ok(())
    }

    fn update(&mut self, _ctx: &mut Context, time: GameTime) -> Result<()> {
        let t = time.total_seconds() as f32;
        for (i, s) in self.orbiters.iter_mut().enumerate() {
            let a = t * 0.8 + i as f32 * std::f32::consts::TAU / 24.0;
            s.transform.translation.x = 400.0 + a.cos() * 180.0;
            s.transform.translation.y = 300.0 + a.sin() * 180.0;
        }
        // Refresh the string twice a second, not every frame: a String
        // allocation at 2 Hz is free; at 60 Hz it is a smell.
        self.acc += time.delta_seconds();
        self.frames += 1;
        if self.acc >= 0.5 {
            self.text = format!("{:5.1} FPS", self.frames as f32 / self.acc);
            self.acc = 0.0;
            self.frames = 0;
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> Result<()> {
        // ... the game scene draws first ...
        for s in &self.orbiters {
            ctx.draw(s, &self.camera as &dyn Camera)?;
        }
        // ... then the HUD, through the same seams (camera per call).
        let Some(font) = &self.font else { return Ok(()) };
        draw_text(
            ctx,
            font,
            &self.text,
            Vec2::new(8.0, 8.0),
            3.0, // 3x scale: 24 px glyphs
            Color::WHITE,
            &self.camera as &dyn Camera,
        )
    }
}

fn main() -> Result<()> {
    let orbiters = (0..24)
        .map(|i| {
            let hue = i as f32 / 24.0;
            Sprite::solid(Color::rgb(0.3 + 0.7 * hue, 0.8 - 0.5 * hue, 0.9), 0.0, 0.0, 14.0, 14.0)
        })
        .collect();
    run(
        FpsDemo {
            font: None,
            text: "  ...".to_string(),
            acc: 0.0,
            frames: 0,
            orbiters,
            camera: OrthographicCamera::new(800.0, 600.0),
        },
        AppConfig {
            title: "Mawida - fps_text (bitmap font)".to_string(),
            ..Default::default()
        },
    )
}
