use crate::commands::Draw;
use crate::engine::Engine;
use crate::platform::types::TextureResource;
use crate::render::BackendState;
use crate::renderer::shader2d::render::Render;

/// Frame executor for 2D draws (world or UI), mirroring Renderer3DRunner.
pub struct Renderer2DRunner {
    render: Render,
    use_ui_camera: bool,
}

impl Renderer2DRunner {
    /// Create a 2D runner from backend state. If `use_ui_camera` is true, it uses the UI camera.
    pub fn setup(
        backend: &BackendState,
        use_ui_camera: bool,
        depth_format: wgpu::TextureFormat,
    ) -> Self {
        let render = Render::setup(
            backend.device.clone(),
            backend.queue.clone(),
            backend.surface_view_format,
            depth_format,
        );
        Self {
            render,
            use_ui_camera,
        }
    }

    /// Record 2D draws into the provided encoder targeting `color_target`.
    /// `draws` are pairs of (Draw, resolved texture) to avoid per-draw texture lookup here.
    pub fn record(
        &mut self,
        g: &Engine,
        color_target: &wgpu::Texture,
        depth_view: &wgpu::TextureView,
        draws: Vec<(Draw, Option<TextureResource>)>,
        encoder: &mut wgpu::CommandEncoder,
    ) {
        if draws.is_empty() {
            return;
        }

        let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("2D Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view: &color_target.create_view(&wgpu::TextureViewDescriptor::default()),
                resolve_target: None,
                ops: wgpu::Operations {
                    // Offscreen is cleared once per frame by RenderDriver
                    load: wgpu::LoadOp::Load,
                    store: wgpu::StoreOp::Store,
                },
                depth_slice: None,
            })],
            depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
                view: depth_view,
                depth_ops: Some(wgpu::Operations {
                    load: wgpu::LoadOp::Load,
                    store: wgpu::StoreOp::Store,
                }),
                stencil_ops: None,
            }),
            occlusion_query_set: None,
            timestamp_writes: None,
        });

        let view_proj = if self.use_ui_camera {
            g.ui_camera().build_view_projection_matrix()
        } else {
            g.camera().build_view_projection_matrix()
        };
        self.render.frame_pass(view_proj);

        for (draw, texture) in draws.into_iter() {
            self.render.draw(draw, texture);
        }
        self.render.frame_end(&mut pass);
    }
}
