pub(super) use super::super::projection::{LightData, MAX_SPOTLIGHT_SHADOWS};
pub(super) use crate::render::wgpu::passes::shadow_depth::{
    MAX_POINT_LIGHT_SHADOWS, PointLightShadowData,
};

pub(super) const MAX_JOINTS_PER_SKIN: usize = 256;
pub(super) const INITIAL_MAX_SKINS: usize = 100;
pub(super) const INITIAL_MAX_TOTAL_BONES: usize = 5_000;
pub(super) const INITIAL_SKINNED_VERTEX_COUNT: usize = 100_000;
pub(super) const INITIAL_SKINNED_INDEX_COUNT: usize = 300_000;
pub(super) const INITIAL_OBJECT_COUNT: usize = 100;
pub(super) const INITIAL_MORPH_DISPLACEMENT_COUNT: usize = 100_000;
pub(super) const MAX_LIGHTS: usize = 128;

#[repr(C, align(256))]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(super) struct SkinnedMeshUniforms {
    pub(super) view: [[f32; 4]; 4],
    pub(super) projection: [[f32; 4]; 4],
    pub(super) camera_position: [f32; 4],
    pub(super) num_lights: [u32; 4],
    pub(super) ambient_light: [f32; 4],
    pub(super) light_view_projection: [[f32; 4]; 4],
    pub(super) shadow_bias: f32,
    pub(super) shadows_enabled: f32,
    pub(super) global_unlit: f32,
    pub(super) shadow_normal_bias: f32,
    pub(super) snap_resolution: [f32; 2],
    pub(super) snap_enabled: u32,
    pub(super) affine_enabled: u32,
    pub(super) fog_color: [f32; 3],
    pub(super) fog_enabled: u32,
    pub(super) fog_start: f32,
    pub(super) fog_end: f32,
    pub(super) cascade_count: u32,
    pub(super) _padding2: f32,
    pub(super) cascade_view_projections:
        [[[f32; 4]; 4]; crate::render::wgpu::passes::NUM_SHADOW_CASCADES],
    pub(super) cascade_split_distances: [f32; crate::render::wgpu::passes::NUM_SHADOW_CASCADES],
    pub(super) cascade_atlas_offsets: [[f32; 4]; crate::render::wgpu::passes::NUM_SHADOW_CASCADES],
    pub(super) cascade_atlas_scale: [f32; 4],
    pub(super) time: f32,
    pub(super) _padding_align: [f32; 3],
    pub(super) directional_light_direction: [f32; 4],
    pub(super) _padding3: [f32; 20],
}

#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(super) struct SkinnedObjectData {
    pub(super) transform_index: u32,
    pub(super) mesh_id: u32,
    pub(super) material_id: u32,
    pub(super) joint_offset: u32,
    pub(super) morph_weights: [f32; 8],
    pub(super) morph_target_count: u32,
    pub(super) morph_displacement_offset: u32,
    pub(super) mesh_vertex_offset: u32,
    pub(super) mesh_vertex_count: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(super) struct MorphDisplacement {
    pub(super) position: [f32; 3],
    pub(super) _pad0: f32,
    pub(super) normal: [f32; 3],
    pub(super) _pad1: f32,
    pub(super) tangent: [f32; 3],
    pub(super) _pad2: f32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct MaterialData {
    pub base_color: [f32; 4],
    pub emissive_factor: [f32; 3],
    pub alpha_mode: u32,
    pub alpha_cutoff: f32,
    pub has_base_texture: u32,
    pub has_emissive_texture: u32,
    pub has_normal_texture: u32,
    pub has_metallic_roughness_texture: u32,
    pub has_occlusion_texture: u32,
    pub normal_scale: f32,
    pub occlusion_strength: f32,
    pub roughness: f32,
    pub metallic: f32,
    pub unlit: u32,
    pub normal_map_flags: u32,
    pub uv_scale: [f32; 2],
    pub transmission_factor: f32,
    pub has_transmission_texture: u32,
    pub thickness: f32,
    pub has_thickness_texture: u32,
    pub _align_attenuation: [u32; 2],
    pub attenuation_color: [f32; 3],
    pub attenuation_distance: f32,
    pub ior: f32,
    pub specular_factor: f32,
    pub _align_specular: [u32; 2],
    pub specular_color_factor: [f32; 3],
    pub has_specular_texture: u32,
    pub has_specular_color_texture: u32,
    pub emissive_strength: f32,
    pub _padding: [u32; 2],
}

pub const NORMAL_MAP_FLIP_Y: u32 = 1;
pub const NORMAL_MAP_TWO_COMPONENT: u32 = 2;

#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub(super) struct MaterialTextures {
    pub(super) base_texture: Option<String>,
    pub(super) emissive_texture: Option<String>,
    pub(super) normal_texture: Option<String>,
    pub(super) metallic_roughness_texture: Option<String>,
    pub(super) occlusion_texture: Option<String>,
    pub(super) transmission_texture: Option<String>,
    pub(super) thickness_texture: Option<String>,
    pub(super) specular_texture: Option<String>,
    pub(super) specular_color_texture: Option<String>,
}

#[derive(Debug, Clone)]
pub(super) struct SkinnedMeshData {
    pub(super) vertex_offset: u32,
    pub(super) vertex_count: u32,
    pub(super) index_offset: u32,
    pub(super) index_count: u32,
    pub(super) _skin_index: u32,
    pub(super) morph_displacement_offset: u32,
    pub(super) morph_target_count: u32,
}
