use rendering::Element;
use rendering::Intersectable;
use rendering::Ray;
use vector::Vector3;

pub struct Intersection<'a> {
    pub distance: f32,
    pub object: &'a Element,
}

impl<'a> Intersection<'a> {
    pub fn new(distance: f32, object: &Element) -> Intersection {
        Intersection { distance, object }
    }
}

pub struct Color {
    pub red: f32,
    pub green: f32,
    pub blue: f32,
}

impl Color {
    pub fn to_rgba(&self) -> [u8; 4] {
        let v: [u8; 4] = [
            (255. * self.red) as u8,
            (255. * self.green) as u8,
            (255. * self.blue) as u8,
            255u8,
        ];
        v
    }
}

pub struct Light {
    pub direction: Vector3,
    pub color: Color,
    pub intensity: f32,
}

pub struct Scene {
    pub width: u32,
    pub height: u32,
    pub fov: f32,
    pub elements: Vec<Element>,
    pub light: Light,
}

impl Scene {
    pub fn trace(&self, ray: &Ray) -> Option<Intersection> {
        self.elements
            .iter()
            .filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s)))
            .min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap())
    }
}
