//! Stage 2 example: open a window, clear it to a configurable color.
//!
//! Run with:
//!   cargo run -p oxide-examples --bin hello_window
//!
//! Controls:
//!   1–5    select a preset clear color
//!   Space  cycle to the next preset
//!   Esc    quit
//!
//! Average FPS is logged once per second, which makes the "stable 60+ FPS"
//! test criterion observable from the terminal.

#![deny(warnings)]

use oxide_engine::prelude::*;
use oxide_engine::window::event::Key;
use oxide_engine::window::event::{ElementState, KeyCode, NamedKey, PhysicalKey, WindowEvent};

const PRESETS: [(&str, Color); 5] = [
    ("cornflower blue", Color::rgba(0.39, 0.58, 0.93, 1.0)),
    ("oxide red", Color::rgba(0.55, 0.15, 0.08, 1.0)),
    ("forest green", Color::rgba(0.05, 0.35, 0.12, 1.0)),
    ("near black", Color::rgba(0.02, 0.02, 0.03, 1.0)),
    ("white", Color::WHITE),
];

#[derive(Default)]
struct HelloWindow {
    preset: usize,
    frames: u32,
    elapsed: f32,
}

impl HelloWindow {
    fn apply_preset(&mut self, ctx: &mut AppCtx<'_>, index: usize) {
        self.preset = index % PRESETS.len();
        let (name, color) = PRESETS[self.preset];
        ctx.set_clear_color(color);
        log::info!("clear color {} — {name}", self.preset + 1);
    }
}

impl WindowApp for HelloWindow {
    fn init(&mut self, ctx: &mut AppCtx<'_>) {
        self.apply_preset(ctx, 0);
        log::info!("press 1–5 to pick a color, Space to cycle, Esc to quit");
    }

    fn event(&mut self, ctx: &mut AppCtx<'_>, event: &WindowEvent) {
        let WindowEvent::KeyboardInput { event: key, .. } = event else {
            return;
        };
        if key.state != ElementState::Pressed {
            return;
        }
        if key.logical_key == Key::Named(NamedKey::Escape) {
            ctx.request_exit();
            return;
        }
        match key.physical_key {
            PhysicalKey::Code(KeyCode::Digit1) => self.apply_preset(ctx, 0),
            PhysicalKey::Code(KeyCode::Digit2) => self.apply_preset(ctx, 1),
            PhysicalKey::Code(KeyCode::Digit3) => self.apply_preset(ctx, 2),
            PhysicalKey::Code(KeyCode::Digit4) => self.apply_preset(ctx, 3),
            PhysicalKey::Code(KeyCode::Digit5) => self.apply_preset(ctx, 4),
            PhysicalKey::Code(KeyCode::Space) => self.apply_preset(ctx, self.preset + 1),
            _ => {}
        }
    }

    fn update(&mut self, ctx: &mut AppCtx<'_>) {
        self.frames += 1;
        self.elapsed += ctx.dt;
        if self.elapsed >= 1.0 {
            log::info!("{:.0} FPS", self.frames as f32 / self.elapsed);
            self.frames = 0;
            self.elapsed = 0.0;
        }
    }
}

fn main() -> anyhow::Result<()> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
    let config = WindowConfig {
        title: "Oxide — hello_window".to_string(),
        width: 960,
        height: 540,
        ..Default::default()
    };
    run(config, HelloWindow::default())
}
