//	TimeAttack.cpp - The main TimeAttack game mode.
//  ----------------------------------------------------------------------------
//	This file is part of 'GameTemplate', template code for a game.
//	Copyright (C) 2011  Niall Moody
//	
//	This program 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.
//
//	This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#include "generators/PickupGenerator.h"
#include "drawing/Drawer.h"
#include "PitchFactory.h"
#include "DebugHeaders.h"
#include "TonesSounder.h"
#include "Application.h"
#include "TimeAttack.h"

#include <sstream>
#include <algorithm>

using namespace std;

//------------------------------------------------------------------------------
GameStateCreator<TimeAttack> TimeAttack::creator;

//------------------------------------------------------------------------------
TimeAttack::TimeAttack(Application& app, SounderPtr& sound):
GameState(app, sound),
gameCore(dynamic_pointer_cast<TonesSounder>(sound)),
lastTicks(0),
secondsRemaining(300),
gameOverCount(30),
paused(false),
sounder(dynamic_pointer_cast<TonesSounder>(sound))
{
	globalData = dynamic_pointer_cast<TonesGlobalData>(getGlobalData());

	gameCore.setPure(globalData->getPure());
	gameCore.setZen(globalData->getZen());
	gameCore.setGameCounter(globalData->getCounter());

	globalData->getCounter()->reset();
	globalData->getCounter()->incrementCount(L"Lives", 3, false);

	sounder->setPitches(PitchFactory::getInstance().getPitches(5));
	gameCore.setNumRails(5);

	gameCore.setCallback(this);
}

//------------------------------------------------------------------------------
TimeAttack::~TimeAttack()
{
	sounder->setGlobalPitch(1.0f);
}

//------------------------------------------------------------------------------
void TimeAttack::update()
{
	float tempf;
	uint32_t newTicks;

	if(!paused)
	{
		newTicks = getApplication().getTimeSinceStart();
		if(lastTicks > 0)
		{
			tempf = (float)(newTicks-lastTicks);
			tempf *= 0.001f;
			if(secondsRemaining > 0.0f)
				secondsRemaining -= tempf;
			else
			{
				secondsRemaining = 0.0f;

				globalData->updateTimeAttackScores(globalData->getCounter()->getScore());
			}
		}
		lastTicks = newTicks;

		if(secondsRemaining > 0.0f)
			gameCore.tick();
		else if(gameOverCount)
		{
			if(gameOverCount == 30)
			{
				//Pause all the tones.
				gameCore.setPause(true, true);
			}

			--gameOverCount;
		}
	}
}

//------------------------------------------------------------------------------
void TimeAttack::draw(DrawerPtr& d, float timestepInterp)
{
	wstringstream tempstr;

	//Draw the core of the game.
	gameCore.draw(d, timestepInterp);

	//Draw the score.
	tempstr << globalData->getCounter()->getScore();
	d->drawText(L"Score:",
				L"Font0",
				textLayouts[0],
				TwoFloats(20.0f, 50.0f),
				512.0f,
				TextLayout::Left,
				1.0f,
				ThreeFloats(0.5f));
	d->drawText(tempstr.str(),
				L"Font0",
				TwoFloats(175.0f, 52.0f),
				512.0f,
				TextLayout::Left,
				1.0f,
				ThreeFloats(0.75f));

	//Draw the remaining time.
	tempstr.clear();
	tempstr.str(L"");
	tempstr << (int)(secondsRemaining/60.0f) << L":";
	tempstr.fill(L'0');
	tempstr.width(2);
	tempstr << ((int)secondsRemaining%60);
	d->drawText(tempstr.str(),
				L"Font0",
				TwoFloats(0.0f, 52.0f),
				d->getDrawingAreaSize().x,
				TextLayout::Centre,
				1.0f,
				ThreeFloats(0.5f));

	//Draw the game over text.
	if(secondsRemaining <= 0.0f)
	{
		std::wstringstream scoreText;

		d->drawImage(L"gameOver", TwoFloats(246.0f, 299.0f));

		if(globalData->getTimeAttackLastScore() == globalData->getTimeAttackHighScore())
			scoreText << L"New High Score!\n\n";

		scoreText << L"High Score: " << globalData->getTimeAttackHighScore();
		d->drawText(scoreText.str(),
					L"Font0",
					TwoFloats(0.0f, 140.0f),
					d->getDrawingAreaSize().x,
					TextLayout::Centre,
					1.0f,
					0.5f);
	}

	//Draw paused text.
	if(paused)
	{
		d->drawText(L"(Paused)",
					L"Font0",
					textLayouts[1],
					TwoFloats(0.0f, 120.0f),
					d->getDrawingAreaSize().x,
					TextLayout::Centre,
					1.0f,
					ThreeFloats(0.5f));
	}
}

//------------------------------------------------------------------------------
void TimeAttack::toneCollision()
{
	float speed = gameCore.getGlobalSpeed();

	speed *= 0.75f;
	if(speed < 0.5f)
		speed = 0.5f;

	gameCore.setGlobalSpeed(speed);
}

//------------------------------------------------------------------------------
void TimeAttack::keyDown(const wstring& action,
						const wstring& keyPressed,
						int keyModifier)
{
	if(action == L"Escape")
	{
		if((gameOverCount>0) && !paused)
		{
			paused = true;
			gameCore.setPause(paused);
		}
		else
			nextState(L"TitleScreen");
	}
	else if(paused)
	{
		paused = false;
		gameCore.setPause(paused);
		lastTicks = getApplication().getTimeSinceStart();
	}
}

//------------------------------------------------------------------------------
void TimeAttack::mouseDown(int button, const TwoFloats& pos)
{
	if(secondsRemaining > 0.0f)
	{
		if(paused)
		{
			paused = false;
			gameCore.setPause(paused);
			lastTicks = getApplication().getTimeSinceStart();
		}
		else
			gameCore.mouseDown(button, pos);
	}
	else if(!gameOverCount)
		nextState(L"TitleScreen");
}

//------------------------------------------------------------------------------
void TimeAttack::mouseUp(int button, const TwoFloats& pos)
{
	gameCore.mouseUp(button, pos);
}

//------------------------------------------------------------------------------
void TimeAttack::mouseMove(const TwoFloats& pos)
{
	gameCore.mouseMove(pos);
}
