#include "Text2D.h"
#include "Utils.h"

Text2D::Text2D() : mTextureData(Textures::gDoomFontTexture) {}

void Text2D::Init()
{
	glGenBuffers(1, &mVertexBufferId);
	glGenBuffers(1, &mUVBufferId);

	mShaderId = GLUtils::LoadShaders("media/shaders/Text2D.vert", "media/shaders/Text2D.frag");
	mUniformId = glGetUniformLocation(mShaderId, "myTextureSampler");
}

void Text2D::Print(const char* aText, int aX, int aY, int aSize)
{
	unsigned int length = strlen(aText);

	std::vector<glm::vec2> vertices;
	std::vector<glm::vec2> uvs;
	int xPos = 0;
	int yPos = aY;

	// Fill up the buffers
	for (unsigned int i = 0; i < length; ++i)
	{
		// Added a little support for multiple lines
		if (aText[i] == '\n')
		{
			xPos = 0;
			yPos -= (aSize + aSize/4);
		}
		else
			++xPos;

		// Vertex info
		glm::vec2 vUpLeft	= glm::vec2(aX+xPos*aSize		, yPos+aSize);
		glm::vec2 vUpRight	= glm::vec2(aX+xPos*aSize+aSize	, yPos+aSize);
		glm::vec2 vDownRight= glm::vec2(aX+xPos*aSize+aSize	, yPos);
		glm::vec2 vDownLeft = glm::vec2(aX+xPos*aSize		, yPos);

		// Make the quad
		vertices.push_back(vUpLeft);
		vertices.push_back(vDownLeft);
		vertices.push_back(vUpRight);

		vertices.push_back(vDownRight);
		vertices.push_back(vUpRight);
		vertices.push_back(vDownLeft);

		// UV info
		char c = aText[i];
		float uvx = (c%16)/16.0f;
		float uvy = (c/16)/16.0f;

		glm::vec2 uvUpLeft		= glm::vec2(uvx				, 1.0f - uvy);
		glm::vec2 uvUpRight		= glm::vec2(uvx+1.0f/16.0f	, 1.0f - uvy);
		glm::vec2 uvDownRight	= glm::vec2(uvx+1.0f/16.0f	, 1.0f - (uvy+1.0f/16.0f));
		glm::vec2 uvDownLeft	= glm::vec2(uvx				, 1.0f - (uvy+1.0f/16.0f));

		// Set uv information for quad
		uvs.push_back(uvUpLeft);
		uvs.push_back(uvDownLeft);
		uvs.push_back(uvUpRight);

		uvs.push_back(uvDownRight);
		uvs.push_back(uvUpRight);
		uvs.push_back(uvDownLeft);
	}
	glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec2), &vertices[0], GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, mUVBufferId);
	glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);

	glUseProgram(mShaderId);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, mTextureData.mTexture);
	glUniform1i(mUniformId, 0);

	// Verts
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);

	// UVS
	glEnableVertexAttribArray(1);
	glBindBuffer(GL_ARRAY_BUFFER, mUVBufferId);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

	// Set blending alpha properties
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	// Draw
	glDrawArrays(GL_TRIANGLES, 0, vertices.size());

	glDisable(GL_BLEND);
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
}

void Text2D::CleanUp()
{
	glDeleteBuffers(1, &mVertexBufferId);
	glDeleteBuffers(1, &mUVBufferId);

	glDeleteProgram(mShaderId);
}