use bytemuck::__core::ops::Range;
use bytemuck::{Zeroable, Pod};
use cgmath::Point3;
use std::sync::Arc;
use wgpu::TextureView;
use crate::components::{RangeCopy, Position};
use crate::render::OPENGL_TO_WGPU_MATRIX;


#[repr(C)]
#[derive(Clone, Copy)]
pub struct LightRaw {
    proj: [[f32; 4]; 4],
    pos: [f32; 4],
    color: [f32; 4],
}

unsafe impl Pod for LightRaw {}

unsafe impl Zeroable for LightRaw {}

#[derive(Clone, Debug)]
pub struct DirectionalLight {
    pub color: wgpu::Color,
    pub fov: f32,
    pub depth: RangeCopy<f32>,
    pub target_view: Arc<TextureView>,
}

impl DirectionalLight {
    pub fn to_raw(&self, pos: &Position) -> LightRaw {
        use cgmath::{Deg, EuclideanSpace, Matrix4, PerspectiveFov, Point3, Vector3};

        let point3d = Point3::new(pos.x, pos.y, pos.z);
        let point3d_2 = Point3::new(pos.x, pos.y - 1.0, pos.z);
        let mx_view = Matrix4::look_at(point3d, point3d_2, Vector3::unit_z());

        let projection = PerspectiveFov {
            fovy: Deg(self.fov).into(),
            aspect: 1.0,
            near: self.depth.start,
            far: self.depth.end,
        };
        let mx_correction = OPENGL_TO_WGPU_MATRIX;
        let mx_view_proj =
            mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
        LightRaw {
            proj: *mx_view_proj.as_ref(),
            pos: [pos.x, pos.y, pos.z, 1.0],
            color: [
                self.color.r as f32,
                self.color.g as f32,
                self.color.b as f32,
                1.0,
            ],
        }
    }
}