//! bounce: things visibly not passing through other things (v0.2 step 12).
//!
//! The collision milestone, both halves: the arrow-key quad CLAMPS at the
//! window edges (it used to sail off), and a ball bounces off two walls
//! using circle_vs_aabb. Overlap and MTV are library code (collide.rs);
//! the responses here (clamp, bounce) are game code, on purpose.
//!
//! Run: cargo run --example bounce

use mawida::collide::{circle_vs_aabb, point_vs_aabb, sprite_bounds};
use mawida::math::Vec2;
use mawida::{
    run, Aabb, AppConfig, Camera, Circle, Color, Context, Game, GameTime, Key, MouseButton,
    OrthographicCamera, Result, Sprite,
};

const QUAD: f32 = 64.0;
const BALL_R: f32 = 10.0;

struct Bounce {
    player: Sprite,
    ball: Sprite,
    ball_pos: Vec2,
    ball_vel: Vec2,
    walls: Vec<Aabb>,
    wall_sprites: Vec<Sprite>,
    score: u32,
    camera: OrthographicCamera,
}

impl Game for Bounce {
    fn update(&mut self, ctx: &mut Context, time: GameTime) -> Result<()> {
        let dt = time.delta_seconds();

        // --- the player quad: move, then CLAMP to the window ---
        let mut d = Vec2::ZERO;
        if ctx.input().is_down(Key::Left) {
            d.x -= 1.0;
        }
        if ctx.input().is_down(Key::Right) {
            d.x += 1.0;
        }
        if ctx.input().is_down(Key::Up) {
            d.y -= 1.0;
        }
        if ctx.input().is_down(Key::Down) {
            d.y += 1.0;
        }
        self.player.transform.translation += (d * 300.0 * dt).extend(0.0);

        let (w, h) = ctx.size();
        let max = Vec2::new(w as f32 - QUAD, h as f32 - QUAD); // top-left anchored
        let p = self.player.transform.translation.truncate().clamp(Vec2::ZERO, max);
        self.player.transform.translation = p.extend(0.0); // the quad now STOPS

        // --- the ball: bounce off walls and screen edges ---
        for wall in &self.walls {
            if circle_vs_aabb(Circle { center: self.ball_pos, radius: BALL_R }, *wall) {
                // tall wall: flip x; wide wall: flip y. Response, in game code.
                if wall.half_extents().x < wall.half_extents().y {
                    self.ball_vel.x = -self.ball_vel.x;
                } else {
                    self.ball_vel.y = -self.ball_vel.y;
                }
            }
        }
        if self.ball_pos.x < BALL_R || self.ball_pos.x > w as f32 - BALL_R {
            self.ball_vel.x = -self.ball_vel.x;
        }
        if self.ball_pos.y < BALL_R || self.ball_pos.y > h as f32 - BALL_R {
            self.ball_vel.y = -self.ball_vel.y;
        }
        self.ball_pos += self.ball_vel * dt;
        self.ball.transform.translation =
            (self.ball_pos - Vec2::splat(BALL_R)).extend(0.0);

        // --- click-the-player: a pickup trigger in three lines ---
        if ctx.input().mouse_just_pressed(MouseButton::Left)
            && point_vs_aabb(ctx.input().mouse_position, sprite_bounds(&self.player.transform))
        {
            self.score += 1; // response is game code: here, a pickup trigger
            log::info!("clicked the quad! score = {}", self.score);
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> Result<()> {
        for ws in &self.wall_sprites {
            ctx.draw(ws, &self.camera as &dyn Camera)?;
        }
        ctx.draw(&self.ball, &self.camera as &dyn Camera)?;
        ctx.draw(&self.player, &self.camera as &dyn Camera)
    }
}

fn main() -> Result<()> {
    // Two walls: one tall (bounces x), one wide (bounces y).
    let walls = vec![
        Aabb::from_min_max(Vec2::new(500.0, 150.0), Vec2::new(520.0, 450.0)),
        Aabb::from_min_max(Vec2::new(150.0, 280.0), Vec2::new(400.0, 300.0)),
    ];
    let wall_sprites = walls
        .iter()
        .map(|wl| {
            let size = wl.max - wl.min;
            Sprite::solid(Color::rgb(0.55, 0.55, 0.65), wl.min.x, wl.min.y, size.x, size.y)
        })
        .collect();

    run(
        Bounce {
            player: Sprite::solid(Color::WHITE, 100.0, 100.0, QUAD, QUAD),
            ball: Sprite::solid(Color::rgb(1.0, 0.6, 0.2), 0.0, 0.0, BALL_R * 2.0, BALL_R * 2.0),
            ball_pos: Vec2::new(300.0, 200.0),
            ball_vel: Vec2::new(220.0, 170.0),
            walls,
            wall_sprites,
            score: 0,
            camera: OrthographicCamera::new(800.0, 600.0),
        },
        AppConfig {
            title: "Mawida - bounce (collision)".to_string(),
            ..Default::default()
        },
    )
}
