use anyhow::Result;

use rtchallenge::{
    canvas::Canvas,
    float::consts::PI,
    matrices::Matrix4x4,
    tuples::{Color, Tuple},
    Float,
};

fn draw_dot(c: &mut Canvas, x: usize, y: usize) {
    let red = Color::new(1., 0., 0.);
    c.set(x.saturating_sub(1), y.saturating_sub(1), red);
    c.set(x, y.saturating_sub(1), red);
    c.set(x + 1, y.saturating_sub(1), red);
    c.set(x.saturating_sub(1), y, red);
    c.set(x, y, red);
    c.set(x + 1, y, red);
    c.set(x.saturating_sub(1), y + 1, red);
    c.set(x, y + 1, red);
    c.set(x + 1, y + 1, red);
}
fn main() -> Result<()> {
    let w = 200;
    let h = w;
    let bg = Color::new(0.2, 0.2, 0.2);
    let mut c = Canvas::new(w, h, bg);
    let t = Matrix4x4::translation(0., 0.4, 0.);
    let p = Tuple::point(0., 0., 0.);
    let rot_hour = Matrix4x4::rotation_z(-PI / 6.);

    let mut p = t * p;
    let w = w as Float;
    let h = h as Float;
    // The 'world' exists between -0.5 - 0.5 in X-Y plane.
    // To convert to screen space, we translate by 0.5, scale to canvas size,
    // and invert the Y-axis.
    let world_to_screen =
        Matrix4x4::scaling(w as Float, -h as Float, 1.0) * Matrix4x4::translation(0.5, -0.5, 0.);
    for _ in 0..12 {
        let canvas_pixel = world_to_screen * p;
        draw_dot(&mut c, canvas_pixel.x as usize, canvas_pixel.y as usize);
        p = rot_hour * p;
    }

    let path = "/tmp/eoc4.png";
    println!("saving output to {}", path);
    c.write_to_file(path)?;
    Ok(())
}
