#include "engine.hpp"

#include "../audio/audio.hpp"

#include "chunk_renderer.hpp"

#include <GLFW/glfw3.h>

using namespace polygun::renderer;

namespace polygun::engine {
	void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }

	void Engine::init() {
		// Initialize audio
		polygun::audio::init();

		glfwInit();
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

		GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Polygun", NULL, NULL);
		if (window == NULL) {
			std::cout << "Failed to create GLFW window" << std::endl;
			glfwTerminate();
			return;
		}
		glfwMakeContextCurrent(window);
		glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
		glfwSetCursorPosCallback(window, m_camera.mouse_callback);
		glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

		if (glewInit() != GLEW_OK) {
			std::cout << "GLEW init failed" << std::endl;
			return;
		}

		glEnable(GL_DEPTH_TEST);
		Chunk m_chunk;
		m_chunk.add_node(1, glm::vec3(0, 0, 0));
		ChunkRenderer m_chunk_renderer(&m_chunk);

		m_delta_time = 0;
		m_last_frame = 0;

		while (!glfwWindowShouldClose(window))
		{
			float current_frame = static_cast<float>(glfwGetTime());
			m_delta_time = current_frame - m_last_frame;
			m_last_frame = current_frame;

			// input
			// -----

			if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
				glfwSetWindowShouldClose(window, true);

			if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
				m_camera.process_movement(polygun::engine::FORWARD, m_delta_time);
			if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
				m_camera.process_movement(polygun::engine::BACKWARD, m_delta_time);
			if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
				m_camera.process_movement(LEFT, m_delta_time);
			if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
				m_camera.process_movement(polygun::engine::RIGHT, m_delta_time);
			if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
				m_camera.process_movement(polygun::engine::UP, m_delta_time);
			if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
				m_camera.process_movement(polygun::engine::DOWN, m_delta_time);

			m_camera.update();
			// render
			// ------

			m_chunk_renderer.render(m_camera);

			glfwSwapBuffers(window);
			glfwPollEvents();
		}


		glfwTerminate();
	}
}
