use bytemuck::{Pod, Zeroable};
use encase::ShaderType;
use glam::{Mat4, Vec2, Vec3};

// 2d vertex
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub tex_coord: [f32; 2],
    pub color: [f32; 4],
}

impl Vertex {
    const ATTRS: [wgpu::VertexAttribute; 3] =
        wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2, 2 => Float32x4];

    pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        wgpu::VertexBufferLayout {
            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Vertex,
            attributes: &Self::ATTRS,
        }
    }
}

#[derive(Clone)]
pub struct TextureResource {
    pub texture: wgpu::Texture,
    pub view: wgpu::TextureView,
    pub sampler: wgpu::Sampler,
}

// We need this for Rust to store our data correctly for the shaders
// This is so we can store this in a buffer
#[derive(Debug, Copy, Clone, ShaderType)]
pub struct CameraUniform {
    pub view_proj: Mat4,
}

impl Default for CameraUniform {
    fn default() -> Self {
        Self {
            view_proj: Mat4::IDENTITY,
        }
    }
}

impl CameraUniform {
    pub fn update(&mut self, view_proj: Mat4) {
        self.view_proj = view_proj;
    }
}

// Uniform data for line rendering
#[derive(Debug, Copy, Clone, ShaderType)]
pub struct LineUniform {
    pub start: Vec2,
    pub end: Vec2,
    pub thickness: f32,
    pub dash_length: f32,
    pub gap_length: f32,
    pub dash_offset: f32,
}

// Uniform data for circle rendering
#[derive(Debug, Copy, Clone, ShaderType)]
pub struct CircleUniform {
    pub center: Vec3,
    pub radius: f32,
}
