#pragma once

#include "MultitouchDrawing.h"
#include "Bacterium.h"
#include "Cell.h"
#include "Macrophage.h"

#include "Actors\ParticleActor.h"
#include "Util\MathUtil.h"

#include <vector>
#include <list>
#include <string>

class CellWarsMTManager;
class Background;
class StartScreen;
class EndScreen;
class HelpScreen;

namespace LayerEnum
{
	enum Enum
	{
		Background,
		TimeBars,
		WelcomeText,
		MacrophageTentacles,
		Cell,
		Macrophage,
		SelectionCircle,
		HealthBar,
		ResourceBar,
		Bacterium,
		MultiSelectionCircle,
		SelectionCircleButton,
		HPString,
		FormBackground,
		FormControls,
		ScreenOverlay,
		SplashScreen,
		DebugDrawing,
		Cursor
	};
}

namespace GameStates
{
	enum Enum
	{
		SplashScreen,
		StartScreen,
		HowToPlay,
		Game,
		Invasion,
		EndStats
	};
}

class ScreenOverlay : public Renderable
{
public:
	ScreenOverlay();

	virtual void Start();
	virtual void Stop(); //calls remove on all _objects and deletes them
	virtual void Update(float dt);
	virtual void Render();
	
	virtual void ReceiveMessage(Message *message) {}
};


//CellWarsGameManager is a singleton and inherits from:
//  GameManager -- so we receive update and render calls, plus collision notifications
#define theCellWarsGame CellWarsGameManager::GetInstance()

class CellWarsGameManager : public GameManager
{
public:
	static const float FADE_IN_OUT_TIME;

	static CellWarsGameManager &GetInstance();
	
	virtual ~CellWarsGameManager();
	virtual void Render();
	virtual void Update(float dt);
	
	void showStart();
	void showHelp();
	void startGame();
	void endGame();

	int getReplications(){return replications;}
	int getUpgrades(){return upgrades;}
	int getKilledMacrophages(){return killedMacrophages;}
	int getKilledCells(){return killedCells;}
	float getPlayTime(){return playTime;}
	static float getTimeToSurvive(){return SURVIVAL_TIME;}
	bool isGameSuccess(){return playTime >= SURVIVAL_TIME;}

	void addReplication(){++replications;}
	void addUpgrade(){++upgrades;}
	void addKilledMacrophage(){++killedMacrophages;}
	void addKilledCell(){++killedCells;}

	virtual void SoundEnded(AngelSoundHandle sound);

	virtual void ReceiveMessage(Message* message);
	
	Bacterium* spawnSingleBacterium(Vector2 spawnPos);
	void removeMacrophageFromGame(Macrophage* m);
	void removeCellFromGame(Cell* c);
	void removeBacteriumFromGame(Bacterium* b);
	
	Cell* getNearestCell(Vector2 fromPos);
	Macrophage* getNearestMacrophage(Vector2 fromPos);
	Bacterium* getNearestBacterium(Vector2 fromPos);

	Cell* getNearestCellFromActor(Actor* fromThis);
	Macrophage* getNearestMacrophageActor(Actor* fromThis);
	Bacterium* getNearestBacteriumActor(Actor* fromThis);

	std::list<Bacterium*>* getBacteriaList(){return bacteria;}

	float getMainVolume(){return mainVolume;}
	void setMainVolume(float newVolume){mainVolume = newVolume; if (mainVolume > 1) mainVolume = 1; if (mainVolume < 0) mainVolume = 0;}

	void playUpgradeSound();
	void playReplicateSound();
	AngelSampleHandle getAttackSample(){return attackSample;}
	AngelSampleHandle getMoveSample(){return moveSample;}

	void gotInput(){timeSinceLastInput = 0; gotInputThisFrame = true;}
	
private:
	CellWarsGameManager();
	static CellWarsGameManager *s_CellWarsGameManager;

	static const int NUM_STARTING_BACTERIA;
	static const float TIME_BETWEEN_MACROPHAGE_WAVES;
	static const float TIME_BETWEEN_MACROPHAGE_WAVES_DECREASE_FACTOR;
	static const float MIN_TIME_BETWEEN_MACROPHAGE_WAVES;
	static const float MACROPHAGE_WAVE_INCREASE_FACTOR;
	static const int MAX_NUM_MACROPHAGES;

	static const float SURVIVAL_TIME;
	static const float INVASION_TIME;

	float timeSinceMusicFadeOutStart;
	float timeSinceInvasionStarted;
	float timeSinceLastDestroyedMacrophage;
	float timeSinceStartup;
	float timeSinceLastInput;
	bool gotInputThisFrame;

	float timeSinceLastMacrophages;
	int numMacrophageWaves;
	int numSpawnedMacrophages;
	std::list<Macrophage*> *macrophages;
	
	static const float TIME_BETWEEN_CELLS;
	static const int MAX_NUM_CELLS;
	float timeSinceLastCell;
	int numCellWaves;
	int numSpawnedCells;
	std::list<Cell*> *cells;
	
	static const int MAX_NUM_BACTERIA;
	int numSpawnedBacteria;
	std::list<Bacterium*> *bacteria;

	float mainVolume;
	AngelSampleHandle backgroundMusicSample;
	AngelSampleHandle replicateSample;
	AngelSampleHandle upgradeSample;
	AngelSampleHandle attackSample;
	AngelSampleHandle moveSample;
	
	AngelSoundHandle backgroundMusicSound;
	AngelSoundHandle replicateSound;
	AngelSoundHandle upgradeSound;
	
	Background *background;
	Actor *splashScreen;
	Actor *fadeScreen;
	Actor *leftSide;
	Actor *rightSide;

	StartScreen *startScreen;
	EndScreen *endScreen;
	HelpScreen *helpScreen;

	ParticleActor *bacteriaInvasion;
	void activateBacteriaInvasion(){if (bacteriaInvasion) bacteriaInvasion->SetParticlesPerSecond(100);}
	void deActivateBacteriaInvasion(){if (bacteriaInvasion) bacteriaInvasion->SetParticlesPerSecond(0);}
	void destroyRemainingBacteria(float dt);

	CellWarsMTManager *multiTouchManager;
	MultitouchDrawing *mtDrawing;

	int replications;
	int upgrades;
	int killedMacrophages;
	int killedCells;
	float playTime;
	
	void initAssets();
	void resetGame();
	void showEndStats();
	void showSplashScreenIfGotNoInput();
	
	void addMacrophageToGame(Macrophage* m);
	void addCellToGame(Cell* c);
	void addBacteriumToGame(Bacterium* b);
	void SpawnMacrophageWave();
	void SpawnBodyCell();
	void SpawnStartBacteria();

	float getCurrentTimeBetweenMacrophages(){
		float res = TIME_BETWEEN_MACROPHAGE_WAVES * exp(-TIME_BETWEEN_MACROPHAGE_WAVES_DECREASE_FACTOR * numMacrophageWaves);
		if (res < MIN_TIME_BETWEEN_MACROPHAGE_WAVES)
			res = MIN_TIME_BETWEEN_MACROPHAGE_WAVES;
		return res;
	}

	GameStates::Enum currentGameState;
};
