// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use std::rc::Rc;

use glium::{Surface, VertexBuffer, Display, Frame, DrawParameters, index::{NoIndices, PrimitiveType}, uniforms::SamplerWrapFunction, uniform};
use glutin::surface::WindowSurface;
use glam::{Vec2, Mat4};

use super::smooth::LocalPlayer;

use crate::app::player_gfx::{PlayerGfx, Instance};
use crate::utils::glium_resize;

pub struct PlayerRenderer {
	gfx: Rc<PlayerGfx>,
	i_vbo: VertexBuffer<Instance>,
	instance_buf: Vec<Instance>,
}

impl PlayerRenderer {
	pub fn new(display: &Display<WindowSurface>, gfx: Rc<PlayerGfx>) -> PlayerRenderer {
		PlayerRenderer {
			gfx,
			i_vbo: VertexBuffer::empty_persistent(display, 1).unwrap(),
			instance_buf: Vec::with_capacity(1),
		}
	}

	pub fn push(&mut self, player: &LocalPlayer, tint: f32, time_diff: f32) {
		self.instance_buf.push(Instance {
			i_pos: player.get_pos(time_diff).into(),
			i_dir: Vec2::from(player.get_dir()).into(),
			i_colour: player.player.get_colour().into(),
			i_layer: player.player.get_texture().get_layer(),
			i_brightness: tint,
			i_alpha: 1.0,
		});
	}

	pub fn render(&mut self, display: &Display<WindowSurface>, frame: &mut Frame, params: &DrawParameters, proj_matrix: &Mat4) {
		let count = self.instance_buf.len();
		glium_resize::vbo_persistent(&mut self.i_vbo, display, count);

		{
			let mut buf = self.i_vbo.map_write();
			for (i, inst) in self.instance_buf.drain(..).enumerate() {
				buf.set(i, inst);
			}
		}

		let uniforms = uniform! { u_matrix: proj_matrix.to_cols_array_2d(), u_texture: self.gfx.textures.sampled().wrap_function(SamplerWrapFunction::Clamp) };
		frame.draw((&self.gfx.v_vbo, self.i_vbo.slice(..count).unwrap().per_instance().unwrap()), NoIndices(PrimitiveType::TrianglesList), &self.gfx.program, &uniforms, params).unwrap();
	}
}
