#include "graphics/tile.h"
#include "graphics/texture.h"
#include "graphics/tiletype.h"

TileSet::TileSet(const char* tileSetImage, float frameSize)
{
	texture->loadTexture(tileSetImage);
	setupTiles(frameSize);
}

void TileSet::setupTiles(float frameSize)
{
	int width = texture->getWidth();
	int height = texture->getHeight();
	float frameRows = height / frameSize;
	float frameCols = width / frameSize;
	int frame = 0;

	float indices[] = {
		0, 1, 2,
		3, 2, 0
	};

	for (int row = 0; row < frameRows; row++)
	{
		for (int column = 0; column < frameCols; column++)
		{
			float left    = (column) * (frameSize / width);
			float right   = (column + 1) * (frameSize / width);
			float bottom  = (row) * (frameSize / height);
			float top	  = (row + 1) * (frameSize / height);
			float vertices[] = {
				0.0f, 0.0f, 0.0f, left, bottom,  // bottom left
				1.0f, 0.0f, 0.0f, right, bottom, // bottom right
				1.0f, 1.0f, 0.0f, right, top,    // top right
				0.0f, 1.0f, 0.0f, left, top		 // top left
			};
			unsigned VAO, EBO, VBO;
			glGenVertexArrays(1, &VAO);
			glGenBuffers(1, &EBO);
			glGenBuffers(1, &VBO);

			glBindVertexArray(VAO);
			glBindBuffer(GL_VERTEX_ARRAY, VBO);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

			glBufferData(GL_VERTEX_ARRAY, sizeof(vertices), vertices, GL_STATIC_DRAW);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
			glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
			glEnableVertexAttribArray(0);
			glEnableVertexAttribArray(1);

			glBindBuffer(GL_VERTEX_ARRAY, 0);
			glBindVertexArray(0);

			tiles[(TileType)frame++] = std::make_shared<TileTexture>(TileTexture({ this->texture, VAO, EBO, VBO }));
		}
	}
}

const std::shared_ptr<TileTexture>& TileSet::getTileTexture(TileType tileType) const
{
	auto tile = tiles.find(tileType);
	if (tile != tiles.end())
		return tile->second;
	return nullptr;
}

TileSet::~TileSet()
{
	delete texture;
	for (auto& [type, tile] : tiles)
	{
		glDeleteBuffers(1, &tile->EBO);
		glDeleteBuffers(1, &tile->VBO);
		glDeleteVertexArrays(1, &tile->VAO);
	}
}
