#include "opengl/opengl_render_path.hpp"
#include "opengl/opengl_renderer.hpp"
#include "opengl/opengl.h"
#include "rive/contour_stroke.hpp"

using namespace rive;

OpenGLRenderPath::OpenGLRenderPath() { glGenBuffers(1, &m_ContourBuffer); }

OpenGLRenderPath::~OpenGLRenderPath() { glDeleteBuffers(1, &m_ContourBuffer); }
void OpenGLRenderPath::fillRule(FillRule value) { m_FillRule = value; }

void OpenGLRenderPath::stencil(OpenGLRenderer* renderer, const Mat2D& transform)
{
	if (isContainer())
	{
		for (auto& subPath : m_SubPaths)
		{
			Mat2D pathTransform;
			// Mat2D::multiply(pathTransform, transform, subPath.transform());
			Mat2D::multiply(pathTransform, transform, subPath.transform());
			reinterpret_cast<OpenGLRenderPath*>(subPath.path())
			    ->stencil(renderer, pathTransform);
		}
		return;
	}

	// glUseProgram(renderer->program());
	std::size_t vertexCount;

	if (isDirty())
	{
		computeContour();
		vertexCount = m_ContourVertices.size();
		// We only want the indices to go from the off contour point (bounds'
		// last point). First 4 points are bounds.
		renderer->updateIndexBuffer(vertexCount - 3);

		glBindBuffer(GL_ARRAY_BUFFER, m_ContourBuffer);
		glBufferData(GL_ARRAY_BUFFER,
		             vertexCount * 2 * sizeof(float),
		             &m_ContourVertices[0][0],
		             GL_DYNAMIC_DRAW);
	}
	else
	{
		glBindBuffer(GL_ARRAY_BUFFER, m_ContourBuffer);
		vertexCount = m_ContourVertices.size();
	}

	// 4 vertices of bounds and one for the repeated start (repeated on close so
	// we don't need to modulate indices and share them across all paths with
	// different contours).
	if (vertexCount < 5)
	{
		return;
	}

	auto triangleCount = vertexCount - 5;
	// printf("VCOUNT: %i E: %i\n", vertexCount, triangleCount);
	// printf("X: %f %f\n", transform[0], transform[1]);
	// printf("Y: %f %f\n", transform[2], transform[3]);
	// printf("T: %f %f\n", transform[4], transform[5]);

	float m4[16] = {transform[0],
	                transform[1],
	                0.0,
	                0.0,
	                transform[2],
	                transform[3],
	                0.0,
	                0.0,
	                0.0,
	                0.0,
	                1.0,
	                0.0,
	                transform[4],
	                transform[5],
	                0.0,
	                1.0};

	glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * 4, (void*)0);

	// glDisable(GL_CULL_FACE);
	// glDisable(GL_DEPTH_TEST);
	// glEnable(GL_BLEND);
	// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->indexBuffer());
	// Index buffer offset is always after first 6 (2 triangles for bounds).

	// Draw the triangulated contour (triangle fans from the bottom left of the
	// AABB) into the stencil buffer.
	glDrawElements(GL_TRIANGLES,
	               triangleCount * 3,
	               GL_UNSIGNED_SHORT,
	               (void*)(6 * sizeof(unsigned short)));

	// GLenum err;
	// while ((err = glGetError()) != GL_NO_ERROR)
	// {
	// 	// Process/log the error.
	// 	fprintf(stderr, "ERRR:: %i\n", err);
	// }
	// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	// static unsigned short indices[3] = {0, 2, 2};
	// glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &indices[0]);
}

void OpenGLRenderPath::cover(OpenGLRenderer* renderer,
                             const Mat2D& transform,
                             const Mat2D& localTransform)
{
	if (isContainer())
	{
		for (auto& subPath : m_SubPaths)
		{
			const Mat2D& subPathTransform = subPath.transform();
			Mat2D pathTransform;
			Mat2D::multiply(pathTransform, transform, subPathTransform);
			reinterpret_cast<OpenGLRenderPath*>(subPath.path())
			    ->cover(renderer, pathTransform, subPathTransform);
		}
		return;
	}

	glBindBuffer(GL_ARRAY_BUFFER, m_ContourBuffer);
	auto vertexCount = m_ContourVertices.size();

	if (vertexCount < 5)
	{
		return;
	}

	{
		float m4[16] = {transform[0],
		                transform[1],
		                0.0,
		                0.0,
		                transform[2],
		                transform[3],
		                0.0,
		                0.0,
		                0.0,
		                0.0,
		                1.0,
		                0.0,
		                transform[4],
		                transform[5],
		                0.0,
		                1.0};

		glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4);
	}
	{
		float m4[16] = {localTransform[0],
		                localTransform[1],
		                0.0,
		                0.0,
		                localTransform[2],
		                localTransform[3],
		                0.0,
		                0.0,
		                0.0,
		                0.0,
		                1.0,
		                0.0,
		                localTransform[4],
		                localTransform[5],
		                0.0,
		                1.0};

		glUniformMatrix4fv(
		    renderer->shapeTransformUniformIndex(), 1, GL_FALSE, m4);
	}

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * 4, (void*)0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->indexBuffer());

	// Draw bounds.
	glDrawElements(GL_TRIANGLES, 2 * 3, GL_UNSIGNED_SHORT, (void*)(0));
}

void OpenGLRenderPath::renderStroke(ContourStroke* stroke,
                                    OpenGLRenderer* renderer,
                                    const Mat2D& transform,
                                    const Mat2D& localTransform)
{
	if (isContainer())
	{
		for (auto& subPath : m_SubPaths)
		{
			reinterpret_cast<OpenGLRenderPath*>(subPath.path())
			    ->renderStroke(stroke, renderer, transform, localTransform);
		}
		return;
	}

	{
		float m4[16] = {transform[0],
		                transform[1],
		                0.0,
		                0.0,
		                transform[2],
		                transform[3],
		                0.0,
		                0.0,
		                0.0,
		                0.0,
		                1.0,
		                0.0,
		                transform[4],
		                transform[5],
		                0.0,
		                1.0};

		glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4);
	}
	{
		float m4[16] = {localTransform[0],
		                localTransform[1],
		                0.0,
		                0.0,
		                localTransform[2],
		                localTransform[3],
		                0.0,
		                0.0,
		                0.0,
		                0.0,
		                1.0,
		                0.0,
		                localTransform[4],
		                localTransform[5],
		                0.0,
		                1.0};

		glUniformMatrix4fv(
		    renderer->shapeTransformUniformIndex(), 1, GL_FALSE, m4);
	}

	std::size_t start, end;
	stroke->nextRenderOffset(start, end);

	glDrawArrays(GL_TRIANGLE_STRIP, start, end - start);
}