use cgmath::{Matrix4,SquareMatrix,Vector3};
use model::Model;

pub enum SceneGraph<'a> {
    Translate(f32, f32, f32, Box<SceneGraph<'a>>),
    Model(&'a Model),
    Many(Vec<SceneGraph<'a>>),
}

impl<'a> SceneGraph<'a> {
    /// Call the supplied callback on every element of a scene graph
    /// along with its calculated transform matrix
    pub fn traverse<F>(&self, callback: &mut F)
        where F: FnMut(&Model, &[[f32;4];4]) -> ()
    {
        self.go(callback, Matrix4::identity() * 0.01);
    }

    fn go<F>(&self, callback: &mut F, mat: Matrix4<f32>)
        where F: FnMut(&'a Model, &[[f32;4];4]) -> ()
    {
        match self {
            &SceneGraph::Model(ref m) => callback(m, &mat.into()),
            &SceneGraph::Many(ref graphs) => for g in graphs {
                g.go(callback, mat);
            },
            &SceneGraph::Translate(x, y, z, ref rs) =>
                rs.go(callback, mat * Matrix4::from_translation(Vector3::new(x, y, z))),
        }
    }
}
