#include "gameplay/map.h"
#include "utility/xmlloader.h"
#include "graphics/tiletype.h"
#include "graphics/shader.h"
#include "gameplay/camera.h"

#include <glm/gtc/matrix_transform.hpp>

Map::Map(const std::shared_ptr<MapData>& mapData, const std::shared_ptr<Shader>& shader) :
	shader(shader), 
	mapData(mapData)
{
	instanceHandle = std::make_shared<TileTextureInstance>(this->mapData->file.c_str());
	tileIds = mapData->groundTiles;
	loadMap();
	createCollisionMap();
}

void Map::loadMap()
{
	for (int y = 0; y < tileIds.size(); y++)
	{
		for (int x = 0; x < tileIds[y].size(); x++)
		{
			glm::mat4 modelMatrix = 
				glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) *
				glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f));
			int tileIndex = static_cast<int>(tileIds[y][x]->spriteID);
			tileData.push_back({ modelMatrix, tileIndex });
		}
	}
	shader->use();
	// TODO: Figure someway to put these in with my xml data
	shader->setInt("tilesPerRow", 8);
}

void Map::createCollisionMap()
{
	for (int y = 0; y < mapData->groundTiles.size(); y++)
	{
		std::vector<int> row;
		for (int x = 0; x < mapData->groundTiles[y].size(); x++)
		{
			if ((int)mapData->groundTiles[y][x]->tileData & (int)Tile::TileData::TILE_UNWALKABLE)
				row.push_back(1);
			else
				row.push_back(0);
		}
		collisionMap.push_back(row);
	}
}

void Map::render(const std::shared_ptr<Camera>& camera)
{
	shader->use();
	shader->setMatrix4f("proj", glm::value_ptr(camera->getProjectionMatrix()));
	shader->setMatrix4f("view", glm::value_ptr(camera->getViewMatrix()));
	instanceHandle->updateInstanceData(tileData);
	instanceHandle->draw();
}