#include <iostream>
#include <cmath>
#include <ctime> 
#include <windows.h>

#define GLEW_STATIC
#include <glew.h>
#include <glfw3.h>

#include <glm\glm\glm.hpp>
#include <glm\glm\gtc\matrix_transform.hpp>
#include <glm\glm\gtc\type_ptr.hpp>
#include <glm\glm\gtx\transform.hpp>

#include <SOIL.h> 

#include <vector>

#include "Sprite.h"
#include "Render.h"

//инвентарь
class Inventory
{
public:
	int ground = 0; //земля
	int rock = 0; //камень

	//очистить инвентарь
	void clearInventory()
	{
		ground = 0;
		rock = 0;
	}
}base;

// управление
bool keys[1000];
bool buttons[10];

// создание сцены
Render one(800, 600);

//Function prototypes
float normalizedCoordinate(float pos, float sizeWin);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void playerControls(glm::mat4 *view, glm::mat4 *player, Render *scene);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
// Camera
glm::mat4 view2;

// время движения
unsigned int movement_time = 0;
void Game()
{


	glfwPollEvents();
	playerControls(&view2, &one.Sprites[0].spriteLocations, &one);

}

// добавляем новый спрайт
Sprite zemla("Image/Ground.png", 1, 1, 1);
Sprite player("Image/geroy.png", 0.66 * 2, 0.96 * 2, 1);

int main()
{
	HDC hDCScreen = GetDC(NULL);
	int Horres = GetDeviceCaps(hDCScreen, HORZRES);
	int Vertres = GetDeviceCaps(hDCScreen, VERTRES);
	ReleaseDC(NULL, hDCScreen);

	//std::cout<< Horres<< Vertres <<std::endl;






	player.sizeTextureCoords.x = 1.0 / 3.0;
	player.sizeTextureCoords.y = 1.0 / 2.0;

	player.meshSprite = player.createPlane();
	//инициализация glfw управления
	glfwSetKeyCallback(one.window, key_callback);
	glfwSetMouseButtonCallback(one.window, mouse_button_callback);

	one.process = Game;
	one.view = &view2;

	
	zemla.spriteLocations = glm::translate(zemla.spriteLocations, glm::vec3(0.5f, 0.5f, -0.1f));

	player.spriteLocations = glm::translate(player.spriteLocations, glm::vec3(0.0f, 20.0f, -0.2f));
	*one.view = glm::translate(*one.view, glm::vec3(0.0f, -20.0f, 0.0f));

	one.Sprites.push_back(player);


	int y = 0;

	for (int x = -100; x < 100; x++)
	{

		y = 2 * sin(x/5);
		one.Sprites.push_back(zemla);
	
		one.Sprites[one.Sprites.size() - 1].spriteLocations = glm::translate(one.Sprites[one.Sprites.size() - 1].spriteLocations, glm::vec3(x, y, 0.0f));

		for (int z = y; z > -10; z--)
		{
			one.Sprites.push_back(zemla);
			one.Sprites[one.Sprites.size() - 1].spriteLocations = glm::translate(one.Sprites[one.Sprites.size() - 1].spriteLocations, glm::vec3(x, z, 0.0f));
		}
	}



	one.renderStart();

	return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (action == GLFW_PRESS)
		keys[key] = true;
	else if (action == GLFW_RELEASE)
		keys[key] = false;
}

bool SPACE = false;
int chek_SPACE = 0;
GLfloat cameraSpeed = 1.0f / 30;

void playerControls(glm::mat4 *view, glm::mat4 *player, Render *scene)
{
	// Чувствительность
	if (SPACE)
	{
		cameraSpeed = 1.0f / 15;
	}
	else
	{
		cameraSpeed = 1.0f / 30;
	}

	// Колличество шагов
	float go = 3;

	//
	bool oneCollision = false;
	// прыжок игрока
	if (keys[GLFW_KEY_SPACE] && SPACE == false)
	{
		
		*player = glm::translate(*player, glm::vec3(0.0f, -1.0f / 30 *2, -0.0f));
		oneCollision = false;

		for (int i = 1; i < scene->Sprites.size(); i++)
		{
			if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
			{
				oneCollision = true;
				break;
			}
		}

		*player = glm::translate(*player, glm::vec3(0.0f, 1.0f / 30 *2, -0.0f));

		if (oneCollision)
		{
			SPACE = true;
		}	
	}

	if (SPACE)
	{
		if (chek_SPACE < 10)
		{
			chek_SPACE++;
			
			for (int i = 0; i < 6; i++)
			{
				*player = glm::translate(*player, glm::vec3(0.0f, 1.0f / 30, -0.0f));
				oneCollision = false;
				for (int i = 1; i < scene->Sprites.size(); i++)
				{
					if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
					{
						oneCollision = true;
						break;
					}
				}

				if (!oneCollision)
				{
					*view = glm::translate(*view, glm::vec3(0.0f, -1.0f / 30, -0.0f));
				}
				else
				{
					*player = glm::translate(*player, glm::vec3(0.0f, -1.0f / 30, -0.0f));
				}
			}
		}
		else
		{
			chek_SPACE = 0;
			SPACE = false;
		}

	}


	// передвижение
/*
	if (keys[GLFW_KEY_S])
	{
		// полушаги
		for (int i = 0; i < go; i++)
		{
			*player = glm::translate(*player, glm::vec3(0.0f, -cameraSpeed, -0.0f));
			oneCollision = false;
			for (int i = 1; i < scene->Sprites.size(); i++)
			{
				if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
				{
					oneCollision = true;
				}
			}

			if (!oneCollision)
			{
				*view = glm::translate(*view, glm::vec3(0.0f, cameraSpeed, -0.0f));
			}
			else
			{
				*player = glm::translate(*player, glm::vec3(0.0f, cameraSpeed, -0.0f));
			}
		}
	}
	if (keys[GLFW_KEY_W])
	{
		for (int i = 0; i < go; i++)
		{
			*player = glm::translate(*player, glm::vec3(0.0f, cameraSpeed, -0.0f));
			oneCollision = false;
			for (int i = 1; i < scene->Sprites.size(); i++)
			{
				if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
				{
					oneCollision = true;
				}
			}

			if (!oneCollision)
			{
				*view = glm::translate(*view, glm::vec3(0.0f, -cameraSpeed, -0.0f));
			}
			else
			{
				*player = glm::translate(*player, glm::vec3(0.0f, -cameraSpeed, -0.0f));
			}
		}
	}
	*/
	
	// сила тяжести
	if (!SPACE)
	{
		for (int i = 0; i < 7; i++)
		{
			*player = glm::translate(*player, glm::vec3(0.0f, -cameraSpeed, -0.0f));
			oneCollision = false;
			for (int i = 1; i < scene->Sprites.size(); i++)
			{
				if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
				{
					oneCollision = true;
				}
			}

			if (!oneCollision)
			{
				*view = glm::translate(*view, glm::vec3(0.0f, cameraSpeed, -0.0f));
			}
			else
			{
				*player = glm::translate(*player, glm::vec3(0.0f, cameraSpeed, -0.0f));
			}
		}
	}


	// Впарво
	if (keys[GLFW_KEY_D])
	{
		for (int i = 0; i < go; i++)
		{
			*player = glm::translate(*player, glm::vec3(cameraSpeed, 0.0f, -0.0f));
			oneCollision = false;
			for (int i = 1; i < scene->Sprites.size(); i++)
			{
				if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
				{
					oneCollision = true;
					break;
				}
			}

			if (!oneCollision)
			{
				*view = glm::translate(*view, glm::vec3(-cameraSpeed, 0.0f, -0.0f));
				// смена спрайта для движения
				movement_time += one.deltaTime;
				one.Sprites[0].shift.y = 0.5;
				if (movement_time > 300)
				{
					movement_time = 0;
					one.Sprites[0].shift.x -= 1.0 / 3.0;
					if (one.Sprites[0].shift.x < 0.1)
					{
						one.Sprites[0].shift.x = 1;
					}
				}
				one.Sprites[0].meshSprite = one.Sprites[0].createPlane();
			}
			else
			{
				*player = glm::translate(*player, glm::vec3(-cameraSpeed, 0.0f, -0.0f));
			}
		}
	}


	// Влево
	if (keys[GLFW_KEY_A])
	{
		for (int i = 0; i < go; i++)
		{
			*player = glm::translate(*player, glm::vec3(-cameraSpeed, 0.0f, -0.0f));
			oneCollision = false;
			for (int i = 1; i < scene->Sprites.size(); i++)
			{
				if (checkCollision(&scene->Sprites[0], &scene->Sprites[i]))
				{
					oneCollision = true;
					break;
				}
			}

			if (!oneCollision)
			{
				*view = glm::translate(*view, glm::vec3(cameraSpeed, 0.0f, -0.0f));
				// смена спрайта для движения
				movement_time += one.deltaTime;
				one.Sprites[0].shift.y = 1.0;
				if (movement_time > 300)
				{
					movement_time = 0;
					one.Sprites[0].shift.x -= 1.0 / 3.0;
					if (one.Sprites[0].shift.x < 0.1)
					{
						one.Sprites[0].shift.x = 1;
					}				
				}
				one.Sprites[0].meshSprite = one.Sprites[0].createPlane();
			}
			else
			{
				*player = glm::translate(*player, glm::vec3(cameraSpeed, 0.0f, -0.0f));
			}
		}
	}

	// Управление мышью
	if (buttons[GLFW_MOUSE_BUTTON_LEFT])
	{
		// определяем координаты мыши в координатах мира
		double xpos, ypos;
		glfwGetCursorPos(one.window, &xpos, &ypos);
		xpos = normalizedCoordinate(xpos, one.wIDTH);
		ypos = -normalizedCoordinate(ypos, one.hEIGHT);
		xpos = xpos * one.scale + glm::value_ptr(one.Sprites[0].spriteLocations)[12];
		ypos = ypos  * one.scale / one.ratioWindow + glm::value_ptr(one.Sprites[0].spriteLocations)[13];

		// определяем попали ли мы по объекту в игре
		for (int i = 1; i < one.Sprites.size(); i++)
		{
			if (abs(glm::value_ptr(one.Sprites[i].spriteLocations)[12] - xpos) < 0.5 && abs(glm::value_ptr(one.Sprites[i].spriteLocations)[13] - ypos) < 0.5)
			{
				// проверяем тип объекта
				// Удаляем объект и добавляем в инвентарь
				one.Sprites.erase(one.Sprites.begin() + i);
				base.ground++;
			}
		}
		// вывод координат для теста
		//std::cout<< xpos <<"    "<< ypos <<std::endl;
	}

	if (buttons[GLFW_MOUSE_BUTTON_RIGHT])
	{
		// определяем координаты мыши в координатах мира
		double xpos, ypos;
		glfwGetCursorPos(one.window, &xpos, &ypos);
		xpos = normalizedCoordinate(xpos, one.wIDTH);
		ypos = -normalizedCoordinate(ypos, one.hEIGHT);
		xpos = xpos * one.scale + glm::value_ptr(one.Sprites[0].spriteLocations)[12];
		ypos = ypos * one.scale / one.ratioWindow + glm::value_ptr(one.Sprites[0].spriteLocations)[13];

		// делаем заклинание
		if (xpos<0)
		{
			xpos--;
		}
		if (ypos<0)
		{
			ypos--;
		}

		// создаем объект
		one.Sprites.push_back(zemla);
		one.Sprites[one.Sprites.size() - 1].spriteLocations = glm::translate(one.Sprites[one.Sprites.size() - 1].spriteLocations, glm::vec3(int(xpos), int(ypos), 0.0f));
		
		// проверяем где создали его
		oneCollision = false;

		for (int i = 0; i < scene->Sprites.size() - 1; i++)
		{
			if (checkCollision(&scene->Sprites[scene->Sprites.size() - 1], &scene->Sprites[i]))
			{
				oneCollision = true;
				break;
			}
		}

		if (oneCollision)
		{
			one.Sprites.erase(one.Sprites.begin() + scene->Sprites.size() - 1);
		}
		else
		{
			base.ground--;
		}
	}

}

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
	if (action == GLFW_PRESS)
		buttons[button] = true;
	else if (action == GLFW_RELEASE)
		buttons[button] = false;
}

float normalizedCoordinate(float pos, float sizeWin)
{
	float normalizedCoordinate;
	float halfSize = sizeWin /2;
	if (sizeWin > halfSize)
	{
		normalizedCoordinate =(pos - halfSize) / halfSize;
	}
	else
	{
		normalizedCoordinate = 1 - ( pos / halfSize);
	}

	return normalizedCoordinate;
}

