#include <iostream>
#include <opengl-playground/sdlmainwindow.hpp>
#include <opengl-playground/openglshader.hpp>
#include <opengl-playground/textured-rectangle.hpp>
#include <opengl-playground/globalcanvassettings.hpp>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <imgui.h>
#include <imgui_impl_sdl.h>
#include <imgui_impl_opengl3.h>

#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800

unsigned char tex[4*10000] = {255};

int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	SdlMainWindow *window;
	bool run = true;
	glm::mat4 view_matrix;
	glm::mat4 projection_matrix;
	glm::vec4 color = glm::vec4(1.0f);
	float y_rotation = 0.0f;
	bool proj_ortho = true;

	float nav_point[2] = {0.0f, 0.0f};
	float zoom = 1.0;

	for (int i = 0; i < 10000; i++) {
		tex[i*4] = 0xff;
		tex[i*4+1] = 0x00;
		tex[i*4+2] = 0x00;
		tex[i*4+3] = 0xFF;
	}


	window = new SdlMainWindow(WINDOW_HEIGHT, WINDOW_WIDTH);

	window->show();
	window->activateGlContext();

	/* Clear the image and set the background to a nice gray */
	glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
	glClearColor(0.1f, 0.1f, 0.1f, 0.f);
	glClear(GL_COLOR_BUFFER_BIT);

	std::shared_ptr<OpenGlShaderProgram> textured_rect_prog =
			std::make_shared<OpenGlShaderProgram>("shaders/textured-rectangle-vertex.glsl", "",
							      "shaders/textured-rectangle-fragment.glsl");

	projection_matrix = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -1.0f, 1.0f);
	GlobalCanvasSettings::setProjectionMatrix(projection_matrix);
	GlobalCanvasSettings::setViewMatrix(glm::mat4(1.0f));
	textured_rect_prog->compile();

	std::shared_ptr<OpenGlTexture> texture = std::make_shared<OpenGlTexture>();
	texture->setRGBDataFromBytes(100,100, (char*)tex);

	TexturedRectangle rect = TexturedRectangle(-3, -3, 3, 3, textured_rect_prog, texture);
	rect.realize();

	// Setup Dear ImGui context
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();
	ImGuiIO& io = ImGui::GetIO(); (void)io;
	//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
	//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

	// Setup Dear ImGui style
	ImGui::StyleColorsDark();
	//ImGui::StyleColorsClassic();

	// Setup Platform/Renderer bindings
	ImGui_ImplSDL2_InitForOpenGL(window->getWindow(), window->getContext());
	ImGui_ImplOpenGL3_Init("#version 330");


	while (run) {

		SDL_Event event;
		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_MOUSEWHEEL) {
				if (event.wheel.y > 0) {
					zoom += 0.1;
				} else {
					zoom -= 0.1;
				}
			}


			ImGui_ImplSDL2_ProcessEvent(&event);
			if (event.type == SDL_QUIT)
				run = false;
			if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window->getWindow()))
				run = false;
		}


		glClear(GL_COLOR_BUFFER_BIT);

		// Start the Dear ImGui frame
		ImGui_ImplOpenGL3_NewFrame();
		ImGui_ImplSDL2_NewFrame(window->getWindow());
		ImGui::NewFrame();


		view_matrix = glm::scale(glm::mat4(1.0f), glm::vec3(zoom, zoom, 1.0));
		view_matrix = glm::translate(view_matrix, glm::vec3(-nav_point[0], -nav_point[1], -10.0f));

		GlobalCanvasSettings::setViewMatrix(view_matrix);

		rect.render();

		ImGui::Begin("Rectangle");
		ImGui::Text("Change the color of the rectangle below");
		ImGui::NewLine();
		ImGui::SliderFloat4("Rectangle Color", &color.r, 0.0f, 1.0f, "%.3f", 1.0f);
		ImGui::Text("Rectangle Rotation:");
		ImGui::NewLine();
		ImGui::SliderAngle("Y Rotation", &y_rotation, -180.0f, +180.0f);
		static int e = 0;
		ImGui::RadioButton("Orthographic", &e, 0); ImGui::SameLine();
		ImGui::RadioButton("Perspective", &e, 1);

		if(!e) {
			GlobalCanvasSettings::setProjectionMatrix(glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -1.0f, 20.0f));
		} else {

			GlobalCanvasSettings::setProjectionMatrix(glm::perspective(glm::radians(120.0f), (float)1200/(float)800, 1.0f, 30.0f));
		}

		ImGui::End();


		glm::mat4 model_matrix = glm::rotate(glm::mat4(1.0f), y_rotation, glm::vec3(0.0f, 1.0f, 0.0f));
		rect.setModelMatrix(model_matrix);
		rect.setBaseColor(color);
		ImGui::Render();
		ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

		window->swapBuffer();

	}

	ImGui_ImplOpenGL3_Shutdown();
	ImGui_ImplSDL2_Shutdown();
	ImGui::DestroyContext();

	textured_rect_prog->unload();
	delete window;
}
