/**
 * Viewer abstraction to control multiple off-axis cameras
 */

use bevy::{math::Vec4Swizzles, prelude::*, transform};

use crate::{
    offaxis::OffAxisProjection, projection::create_offaxis_matrices, screeninfo::ScreenInfo,
};

#[derive(Component, Default)]
pub struct Viewer {
    pub position: Vec3,
    pub orientation: Quat,

    pub alpha: f32,
}

impl Viewer {
    pub fn new(position: Vec3) -> Self {
        Self {
            position,
            orientation: Quat::IDENTITY,
            alpha: 0.0,
        }
    }

    pub fn default() -> Self {
        Self {
            position: Vec3::ZERO,
            orientation: Quat::IDENTITY,
            alpha: 0.0,
        }
    }
}

pub fn apply_viewer_to_projections(
    mut query: Query<(&Viewer, &ScreenInfo, &mut OffAxisProjection, &mut Transform)>,
) {
    query.for_each_mut(|(viewer, screen_info, mut offaxis, mut transform)| {
        let eye = viewer.position;

        let (lower_left, lower_right, upper_left, _) = screen_info.corner_points();

        // let lower_left = Vec3::new(screen_info.center.x - screen_info.width / 2.0,screen_info.center.y - screen_info.height / 2.0,screen_info.center.z);
        // let upper_left = Vec3::new(screen_info.center.x - screen_info.width / 2.0,screen_info.center.y + screen_info.height / 2.0,screen_info.center.z);

        // let lower_right = Vec3::new(screen_info.center.x + screen_info.width / 2.0,screen_info.center.y - screen_info.height / 2.0,screen_info.center.z);

        let (view, projection) =
            create_offaxis_matrices(lower_left, lower_right, upper_left, eye, 1000.0f32);

        offaxis.projection_matrix = projection;

        *transform = Transform::from_matrix(view.inverse());

        // info!("Viewer {:?}", viewer.position);

        // *transform = Transform::from_translation(eye).looking_at(Vec3::ZERO, Vec3::Y);
    });
}

pub fn simulate_viewer_with_circle(mut query: Query<&mut Viewer>, time: Res<Time>) {
    for mut v in query.iter_mut() {

        let radius = 1.3;
        let offset = Vec3::new(0.0,0.0,8f32);
        let speed = 1.0f32;

        v.alpha += speed * time.delta_seconds();


        v.position = Vec3::new(
            v.alpha.sin() * radius,
            v.alpha.cos() * radius,
            0.0,
        ) + offset;

        // info!("Viewer {:?}", v.position);
    }
}

pub fn simulate_viewer_with_keyboard(
    mut query: Query<&mut Viewer>,
    input: Res<Input<KeyCode>>,
    time: Res<Time>,
) {

    let offset = Vec3::new(0.0,0.0,8f32);

    for mut viewer in query.iter_mut() {
        if input.pressed(KeyCode::W) {
            viewer.position += Vec3::Z * time.delta_seconds();
        } else if input.pressed(KeyCode::S) {
            viewer.position -= Vec3::Z * time.delta_seconds();
        } else if input.pressed(KeyCode::A) {
            viewer.position -= Vec3::X * time.delta_seconds();
        } else if input.pressed(KeyCode::D) {
            viewer.position += Vec3::X * time.delta_seconds();
        } else if input.pressed(KeyCode::Up) {
            viewer.position += Vec3::Y * time.delta_seconds();
        } else if input.pressed(KeyCode::Down) {
            viewer.position -= Vec3::Y * time.delta_seconds();
        }
    }
}