/*
	Copyright 2014 Michele "King_DuckZ" Santullo

	This file is part of CloonelJump.

	CloonelJump is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	CloonelJump is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with CloonelJump.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "gamebase.hpp"
#include "texture.hpp"
#include "sdlmain.hpp"
#include "inputbag.hpp"
#include "key.hpp"
#include <sstream>
#include <SDL2/SDL.h>
#include <ciso646>
#include <cassert>

namespace cloonel {
	namespace {
		///---------------------------------------------------------------------
		///---------------------------------------------------------------------
		bool DoEvents (InputBag& parInput, SDLMain* parSdlMain) {
			SDL_Event eve;
			while (SDL_PollEvent(&eve)) {
				switch (eve.type) {
				case SDL_KEYDOWN:
					//eve.key.keysym.sym
					parInput.NotifyKeyAction(InputDevice_Keyboard, eve.key.keysym.scancode, true);
					break;

				case SDL_KEYUP:
					parInput.NotifyKeyAction(InputDevice_Keyboard, eve.key.keysym.scancode, false);
					break;

				case SDL_QUIT:
					return true;

				case SDL_WINDOWEVENT:
					if (SDL_WINDOWEVENT_RESIZED == eve.window.event) {
						parSdlMain->SetResolution(ushort2(static_cast<uint16_t>(eve.window.data1), static_cast<uint16_t>(eve.window.data2)));
					}
					else if (SDL_WINDOWEVENT_CLOSE == eve.window.event) {
						return true;
					}
					break;
				}
			}
			return false;
		}
	} //unnamed namespace

	///------------------------------------------------------------------------
	///------------------------------------------------------------------------
	GameBase::GameBase (SDLMain* parSdlMain) :
		m_input(new InputBag()),
		m_sdlmain(parSdlMain),
		m_time0(SDL_GetTicks()),
		m_wantsToQuit(false)
	{
	}

	///------------------------------------------------------------------------
	///------------------------------------------------------------------------
	GameBase::~GameBase() noexcept {
	}

	///------------------------------------------------------------------------
	///------------------------------------------------------------------------
	float GameBase::Exec() {
		const unsigned int time1 = SDL_GetTicks();
		const float delta = static_cast<float>(time1 - m_time0) * 0.001f;
		m_time0 = time1;

		SDL_Renderer* const ren = m_sdlmain->GetRenderer();

		SDL_RenderClear(ren);
		OnPreUpdate();
		OnUpdate(delta);
		OnRender();
		SDL_RenderPresent(ren);

		m_wantsToQuit = DoEvents(*m_input, m_sdlmain);
		m_input->KeyStateUpdateFinished();

		return delta;
	}

	///------------------------------------------------------------------------
	///------------------------------------------------------------------------
	bool GameBase::WantsToQuit() const {
		return m_wantsToQuit or ShouldQuit();
	}

	///------------------------------------------------------------------------
	///------------------------------------------------------------------------
	bool GameBase::ShouldQuit() const {
		return false;
	}
} //namespace cloonel
