#include <GL/glew.h>
#include <glm/ext.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_float2x3.hpp>
#include <glm/ext/matrix_projection.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/trigonometric.hpp>
#include <memory>
#include "graphics/context.hpp"
#include "graphics/gl/program.hpp"
#include "graphics/gl/shader.hpp"
#include "graphics/shader/compile.hpp"
#include "graphics/shader/link.hpp"
#include "graphics/window.hpp"
#include "world/map.hpp"
#include "world/player.hpp"
#include "world/tile/empty.hpp"

int main() {
	Graphics::Window window;
	Graphics::GL::Shader model_vert = Graphics::Shader::compile(GL_VERTEX_SHADER, "../assets/shader/model.vert");
	Graphics::GL::Shader model_frag = Graphics::Shader::compile(GL_FRAGMENT_SHADER, "../assets/shader/model.frag");
	Graphics::GL::Program model_p = Graphics::Shader::link({model_vert, model_frag});
	Graphics::Context context(model_p);
	World::Player player;
	World::Map map;

	map.set_tile({0, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({1, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({2, 1}, std::make_unique<World::Tile::Empty>());
	map.set_tile({2, 2}, std::make_unique<World::Tile::Empty>());
	map.set_tile({3, 2}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-1, -1}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-1, -2}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-2, -3}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-1, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-3, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-4, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-5, 0}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-4, 1}, std::make_unique<World::Tile::Empty>());
	map.set_tile({-4, -1}, std::make_unique<World::Tile::Empty>());
	map.set_tile({0, -1}, std::make_unique<World::Tile::Empty>());
	
	glUseProgram(model_p);

	context.set_projection_matrix(glm::perspective(glm::radians(90.0), 800.0 / 600.0, 0.1, 100.0));
	context.set_view_matrix(player.get_view_matrix());

	while(!window.should_close()) {
		map.update();
		window.poll_events();

		glUseProgram(model_p);
		glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
		glClearColor(0.1, 0.1, 0.12, 1);

		map.render(context);
		window.swap_buffers();
	}
}