use bevy::prelude::*;

use bevy::render::primitives::Frustum;
use bevy::render::camera::{Camera, CameraProjection};
use bevy::render::view::VisibleEntities;

#[derive(Component)]
pub struct OffAxisProjection {
    near: f32,
    far: f32,
    aspect: f32,
}

impl CameraProjection for OffAxisProjection {
    fn get_projection_matrix(&self) -> Mat4 {
        println!("Here we go!");
        Mat4::orthographic_rh(
            -self.aspect, self.aspect, -1.0, 1.0, self.near, self.far
        )
    }

    // what to do on window resize
    fn update(&mut self, width: f32, height: f32) {
        self.aspect = width / height;
    }

    // fn depth_calculation(&self) -> DepthCalculation {
    //     // for 2D (camera doesn't rotate)
    //     DepthCalculation::ZDifference

    //     // otherwise
    //     //DepthCalculation::Distance
    // }

    fn far(&self) -> f32 {
        self.far
    }
}

impl Default for OffAxisProjection {
    fn default() -> Self {
        Self { near: 0.0, far: 1000.0, aspect: 1.0 }
    }
}

pub fn camera_setup(mut commands: Commands) {
    print!("Setup {0}",line!());

    // We need all the components that Bevy's built-in camera bundles would add

    let projection = OffAxisProjection::default();

    let camera = Camera {
        // near: projection.near,
        // far: projection.far,
        ..default()
    };

    print!("Setup {0}",line!());

    // position the camera like bevy would do by default for 2D:
    let transform = Transform::from_xyz(0.0, 0.0, projection.far - 0.1);
    // frustum construction code copied from Bevy
    let view_projection =
        projection.get_projection_matrix() * transform.compute_matrix().inverse();
    
	let frustum = Frustum::from_view_projection(
        &view_projection,
        &transform.translation,
        &transform.back(),
        projection.far,
    	);

    print!("Setup {0}",line!());
    
    // commands.spawn_bundle((
    //     camera,
    //     projection,
    //     frustum,
    //     VisibleEntities::default(),
    //     transform,
    //     GlobalTransform::default(),
    //     // Camera2d,
    // )
    // );

	print!("Setup {0}",line!());

}

// fn main() {
//     // need to add a bevy-internal camera system to update
//     // the projection on window resizing

//     use bevy::render::camera::camera_system;

//     App::new()
//         .add_plugins(DefaultPlugins)
//         .add_startup_system(setup)
//         .add_system_to_stage(
//             CoreStage::PostUpdate,
//             camera_system::<SimpleOrthoProjection>,
//         )
//         .run();
// }