use glam::Mat4;

use crate::engine::Engine;
use crate::mesh3d::{Mesh3D, Mesh3DShader};
use crate::renderer::shader3d::draw3d::Draw3D;

/// Frame executor used by the platform to render queued 3D draws.
pub struct Shader3DRunner {
    mesh_shader: Mesh3DShader,
}

impl Shader3DRunner {
    pub fn new(g: &Engine) -> Self {
        Self {
            mesh_shader: Mesh3DShader::new(g),
        }
    }

    pub fn record(
        &mut self,
        g: &Engine,
        color_target: &wgpu::Texture,
        depth_view: &wgpu::TextureView,
        draws: &[Draw3D],
        encoder: &mut wgpu::CommandEncoder,
    ) {
        if draws.is_empty() {
            return;
        }
        let size = color_target.size();
        let aspect = if size.height == 0 {
            1.0
        } else {
            size.width as f32 / size.height as f32
        };
        let view_proj = g.camera3d().view_proj(aspect);
        // Build a temporary slice of (&Mesh3D, Mat4)
        let tmp: Vec<(&Mesh3D, Mat4)> = draws.iter().map(|d| (&d.mesh, d.model)).collect();
        self.mesh_shader
            .record_to_encoder(g, color_target, depth_view, view_proj, &tmp, encoder);
    }
}
