//	GameCore.h - Class encapsulating the core of the game logic.
//  ----------------------------------------------------------------------------
//	This file is part of 'GameTemplate', template code for a game.
//	Copyright (C) 2012  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/>.
//	----------------------------------------------------------------------------

#ifndef GAMECORE_H_
#define GAMECORE_H_

#include "Crash.h"
#include "Player.h"
#include "c0xHeaders.h"
#include "generators/MetaGenerator.h"

class GameCounter;
class TonesSounder;

typedef shared_ptr<TonesSounder> TonesSounderPtr;

///	Class encapsulating the core of the game logic.
class GameCore
{
  public:
	///	Constructor.
	GameCore(TonesSounderPtr sound);
	///	Destructor.
	~GameCore();

	///	Sets pure mode.
	void setPure(bool val);
	///	Sets zen mode.
	void setZen(bool val);
	///	Sets the GameCounter instance.
	void setGameCounter(shared_ptr<GameCounter>& counter);
	///	Sets the current number of rails.
	void setNumRails(int val);

	///	Moves the tones etc.
	void tick();
	///	Draws the tones and background.
	void draw(DrawerPtr& d, float timestepInterp);

	///	Puts us into pause mode.
	void setPause(bool val, bool kill = false);
	///	Updates the global speed.
	void setGlobalSpeed(float val);

	///	Sets whether or not we draw the player.
	void setDontDrawPlayer(bool val);
	///	Ensures all tones are generated with the PickupAutopilotTitle behaviour.
	void setAllTonesAuto(bool val);

	///	Returns the current global speed.
	float getGlobalSpeed() const {return globalSpeed;};

	///	Called when a mouse down event is received.
	void mouseDown(int button, const TwoFloats& pos);
	///	Called when a mouse up event is received.
	void mouseUp(int button, const TwoFloats& pos);
	///	Called when a mouse move event is received.
	void mouseMove(const TwoFloats& pos);

	///	To get informed when Tones collide, implement this class.
	class Callback
	{
	  public:
		///	Constructor.
		Callback() {};
		///	Destructor.
		virtual ~Callback() {};

		///	Called when Tones collide.
		virtual void toneCollision() = 0;
	};
	///	Sets the callback to call when Tones collide.
	void setCallback(Callback *c);
  private:
	///	Helper method. Checks whether any Tones have collided.
	void collisionDetection();

	///	Whether we should be in pure mode or not.
	bool pure;
	///	Whether we should be in zen mode or not.
	bool zen;
	///	Our copy of the GameCounter instance.
	shared_ptr<GameCounter> gameCounter;

	///	Used to generate new Tones.
	MetaGenerator generator;
	///	All the Tones currently in play.
	std::vector<TonePtr> tones;
	///	All the types of Tones currently in play.
	std::map<std::wstring, int> toneTypes;
	///	The number of Tones which are in a warning state (updated every frame).
	int numWarnings;

	///	Any Pickups currently in play.
	std::vector<PickupPtr> pickups;

	///	How many rails there are.
	int numRails;
	///	How many rails there were previously.
	int oldNumRails;
	///	Used to interpolate between the current number of rails and the new number.
	float railInterp;
	///	The current global speed of the Tones.
	float globalSpeed;
	///	Used to reduce globalSpeed when there's a collision.
	float slowDownCount;
	///	The current slowDown value.
	float slowDown;

	///	Used to ensure we only decrease numRails when the effected rails are clear of Tones.
	int numRailsPending;
	///	Used to pulse the rails that are about to be removed when numRailsPending < numRails.
	float railsPulse;

	///	The player deflector.
	Player player;
	///	If true we don't draw the player.
	bool dontDrawPlayer;

	///	If true, all tones are generated with the PickupAutopilotAuto behaviour.
	bool allTonesAuto;

	///	Any crashes currently active.
	std::vector<CrashPtr> crashes;
	///	The remaining time before game over.
	float secondsRemaining;
	///	Used to ensure the player doesn't quit to the title screen too early.
	int gameOverCount;

	///	Used when the player is swiping a Tone.
	TonePtr swipingTone;

	///	Callback to call when Tones collide.
	Callback *callback;

	///	Our copy of the game's sounder.
	TonesSounderPtr sounder;
};

#endif
