
#include <iostream>
#include <Spectre/Game/GameTime.h>
#include <Spectre/Game/FPSCounter.h>
#include <Spectre/Input/InputModule.h>
#include <Spectre/System/Log.h>
#include <Spectre/System/Log/FileWriter.h>
#include <Spectre/System/MessageHandler.h>
#include <Spectre/System/MessageQueue.h>
#include <Spectre/Game.h>

#include <Platform/PlatformApplication.h>
#include <Platform/PlatformMisc.h>

namespace sp {

Game::Game() :
m_running(false)
{
	m_platform = PlatformApplication::get();
	m_graphics = new Graphics(m_platform);
	m_input = new InputModule(&m_platform->getInput());
	m_messageHandler = new MessageHandler();

	// Setup log
	m_log_writer = new log::FileWriter("stdout");
	Log::setWriter(m_log_writer);
}

Game::~Game()
{
	delete m_input;
	delete m_graphics;
	delete m_messageHandler;

	// TODO: This is abit ugly tbh.
	m_platform->shutdown();
}

void Game::run()
{
	m_platform->init();

	if (!m_graphics->init()) {
		return;
	}

	init();

	gameLoop();
}

void Game::gameLoop()
{
	GameTime time;

	time.setTimeStep(120);
	m_running = true;
	while(m_running) {

		processEvents();

		// Update input.
		getInput()->update();

		if (time.beginFrame()) {

			while(time.tick()) {
				update(time.getTimeStep());
			}

			render();
			m_fpsCounter.addFrame();
		}
	}
}

void Game::processEvents()
{
	MessageQueue& queue = m_platform->getMessageQueue();
	Event event;

	while(queue.pollEvent(event)) {

		if (event.type == Event::Quit) {
			exit();
			break;
		}

		// Call message handler.

		if (event.type == Event::Size) {
			m_messageHandler->onSizeChanged(event.size.display, event.size.width, event.size.height);
		}

		m_messageHandler->onEvent(event);
	}
}

void Game::exit()
{
	m_running = false;
}

Graphics* Game::getGraphics() const
{
	return m_graphics;
}

InputModule* Game::getInput() const
{
	return m_input;
}

FPSCounter& Game::getFpsCounter()
{
	return m_fpsCounter;
}

MessageHandler* Game::getMessageHandler() const
{
	return m_messageHandler;
}

} // namespace sp
