#include "gameplay/game.h"
#include "gameplay/input.h"
#include "gameplay/scene.h"

#include "utility/command.h"
#include "utility/resourcemanager.h"
#include "utility/ftfont.h"

#include "graphics/glwindow.h"

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

bool Game::init()
{
	window = std::make_shared<GLWindow>("Yupple Mayham", 800, 600);

	if (!window->Init())
	{
		std::cout << "Failed to init GLWindow: \n" << SDL_GetError() << std::endl;
		return false;
	}

	if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
	{
		std::cout << "Failed to load GLLoader" << std::endl;
		return false;
	}

	SDL_GL_SetSwapInterval(1);
	glViewport(0, 0, window->width(), window->height());
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	// For now we'll init default bindings, but as we move forward controls will be set by the player and saved in controls.xml
	inputHandler = std::make_shared<InputHandler>();
	inputHandler->bindKeyCommand(SDLK_w, 0, new MoveUpCommand());
	inputHandler->bindKeyCommand(SDLK_a, 0, new MoveLeftCommand());
	inputHandler->bindKeyCommand(SDLK_s, 0, new MoveDownCommand());
	inputHandler->bindKeyCommand(SDLK_d, 0, new MoveRightCommand());

	inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, new ShootCommand());
	inputHandler->bindMouseMotion(new FollowMouseCommand());

	game_state |= GAME_RUNNING;
	resourceManager = std::make_shared<ResourceManager>();
	textHandler = std::make_shared<Text>();
	if (!textHandler->loadFonts("fonts"))
		return false;
	textHandler->setProjectionMatrix(glm::ortho(0.f, static_cast<float>(window->width()), 0.f, static_cast<float>(window->height())));
	return true;
}

const unsigned Game::getWindowWidth()	const { return window->width(); }
const unsigned Game::getWindowHeight()	const { return window->height(); }

bool Game::loadDebugScene()
{
	currentScene = std::make_shared<Scene>(SCENE_SHOOTER, resourceManager);
	if (currentScene->getPlayer() == nullptr)
		return false;
	inputHandler->setActor(currentScene->getPlayer().get());
	return true;
}

void Game::handleInput(SDL_Event& e)
{
	inputHandler->captureInput(e);
	inputHandler->handleInput();
}

void Game::update(float deltaTime)
{
	if (currentScene)
		currentScene->update(deltaTime);
}

void Game::render()
{
	glClearColor(0.05f, 0.25f, 0.05f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	if (currentScene)
		currentScene->render();

	window->swap();
}
