#include "pch.h"
#include "Drawer3D.h"

#include "gl/Buffer.h"
#include "gl/Shader.h"
#include "gl/ShaderProgram.h"

Drawer3D::Drawer3D() {
		this->buff = new Buffer(BuffDesc{
			.byte_len = megabyte_in_bytes * 1,
			.subdata_disabled = false,
			.name = "Buff Drawer3D"
		});

	this->buff_ptr = (float*)this->buff->cpu_data;
	this->prev_buff_ptr = (float*)this->buff->cpu_data;
	this->shader_prog= new ShaderProgram({
		new Shader("engine/drawer_3d.vert"),
		new Shader("engine/drawer_3d.frag")
	});
}
void Drawer3D::push_vert(Drawer3DVert v) {
	*buff_ptr++ = v.pos.x;
	*buff_ptr++ = v.pos.y;
	*buff_ptr++ = v.pos.z;
	buff_ptr++;
	*buff_ptr++ = v.color.r;
	*buff_ptr++ = v.color.g;
	*buff_ptr++ = v.color.b;
	*buff_ptr++ = v.color.w;
	this->vert_cnt++;
}
void Drawer3D::draw_line(Drawer3DVert a, Drawer3DVert b) {
	this->push_vert(a);
	this->push_vert(b);
}
void Drawer3D::flush() {
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_DEPTH_TEST);
		glLineWidth(2.0f);

		this->shader_prog->use();
		this->shader_prog->setUniform("drawer_3d_buff", this->buff);
		// int cnt = (buff_ptr - (float*)this->buff->mapped_buff) / (sizeof(Drawer2DVert)/sizeof(float));
		// int cnt = (buff_ptr - (float*)this->buff->mapped_buff) / (sizeof(Drawer2DVert)/sizeof(float));
		// int cnt = (buff_ptr - (float*)this->buff->mapped_buff) / (sizeof(Drawer2DVert)/sizeof(float));
		// glDrawArrays(GL_TRIANGLES, 0, cnt);

		constexpr int floats_per_vert = 8;
		constexpr int bytes_per_vert = 8 * 4;

		int byte_cnt = this->vert_cnt * bytes_per_vert; // 8 floats * 4 bytes

		int float_offs_from_start = this->prev_buff_ptr - (float*)this->buff->cpu_data;
		int byte_offs_from_start = float_offs_from_start * 4;

		this->buff->upload_sub_data(
			this->prev_buff_ptr, byte_cnt, byte_offs_from_start
		);

		// int verts_per_char = 6;
		glDrawArrays(GL_LINES, this->vert_cnt_accum, this->vert_cnt);
		glDisable(GL_BLEND);

		this->vert_cnt_accum += this->vert_cnt;
		this->vert_cnt = 0;
		this->prev_buff_ptr = this->buff_ptr;
}
void Drawer3D::reset() {
		this->vert_cnt = 0;
		this->vert_cnt_accum = 0;
		this->buff_ptr = (float*)this->buff->cpu_data;
		this->prev_buff_ptr = (float*)this->buff->cpu_data;
}
