use anyhow::Result;

use rtchallenge::{
    canvas::Canvas,
    lights::PointLight,
    materials::{lighting, Material},
    rays::Ray,
    shapes::{intersect, Shape},
    tuples::{Color, Tuple},
    Float, WHITE,
};

fn main() -> Result<()> {
    let w = 640;
    let h = w;
    let bg = Color::new(0.2, 0.2, 0.2);
    let mut c = Canvas::new(w, h, bg);
    let ray_origin = Tuple::point(0., 0., -5.);
    let wall_z = 10.;
    let wall_size = 7.;
    let pixel_size = wall_size / w as Float;
    let half = wall_size / 2.;
    let mut shape = Shape::sphere();
    shape.set_material(Material {
        color: Color::new(1., 0.2, 1.),
        specular: 0.5,
        diffuse: 0.7,
        shininess: 30.,
        ..Material::default()
    });
    let light_position = Tuple::point(-10., 10., -10.);
    let light_color = WHITE;
    let light = PointLight::new(light_position, light_color);
    let in_shadow = false;
    for y in 0..h {
        let world_y = half - pixel_size * y as Float;
        for x in 0..w {
            let world_x = -half + pixel_size * x as Float;
            let position = Tuple::point(world_x, world_y, wall_z);
            let direction = (position - ray_origin).normalize();
            let r = Ray::new(ray_origin, direction);
            let xs = intersect(&shape, &r);
            if let Some(hit) = xs.hit() {
                let point = r.position(hit.t);
                let normal = hit.object.normal_at(point);
                let eye = -r.direction;
                let color = lighting(
                    &hit.object.material(),
                    &light,
                    point,
                    eye,
                    normal,
                    in_shadow,
                );
                c.set(x, y, color);
            }
        }
    }

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