#include "StdAfx.h"
#include "Game.h"

#include "Level.h"
#include "Character.h"
#include "SplashScreen.h"
#include <cstdio>

Level *myLvl = NULL;
Character *myChar = NULL;

unsigned int noLevels = 5;
char *levelFiles[6] = {"", "level1.txt", "level2.txt", "level3.txt", "level4.txt", "level5.txt"};

HANDLE ghMutex; 

Game::Game(void)
{
	currentLevel = 1;
	welcome1 = NULL;
	welcome1 = new SplashScreen("Splash1.raw", 300);
	atSplash = 1;
	levelClear = new SplashScreen("LevelClearSplash.raw", 120);
	deathScreen = new SplashScreen("DeathScreenSplash.raw", 120);
	gameOverScreen = new SplashScreen("GameOverSplash.raw", 180);
	gameCompleteScreen = new SplashScreen("GameComplete.raw", 180);

	died = false;
	lComplete = false;
	lives = 3;
	myLvl = new Level();
	myChar = new Character(0, 0);
	myLvl->setCharacter(myChar);
	myLvl->setGame(this);
	myChar->setGame(this);

	string levelString = loadLevelFile(levelFiles[currentLevel]);
	myLvl->loadFromString(levelString);

    ghMutex = CreateMutex( 
        NULL,              // default security attributes
        FALSE,             // initially not owned
        NULL);             // unnamed mutex
}

Game::~Game(void)
{
	if(myLvl)
		delete myLvl;
	delete welcome1;
}

void
Game::die()
{
	died = true;

}

void 
Game::checkState()
{
	if(died)
	{
		died = false;
		lives--;

		if(lives == 0)
		{
			// TODO: Destroy the level and character
			//  and display a "game over" screen.
			atSplash = 4;
			gameOverScreen->resetTimer();

			currentLevel = 1;
			lives = 3;

			// TODO: Destroy and remake the level.
			Level *nLvl = new Level();
			Character *nChar = new Character(0, 0);
			nLvl->setCharacter(nChar);
			nLvl->setGame(this);
			nChar->setGame(this);
			string levelString = loadLevelFile(levelFiles[currentLevel]);
			nLvl->loadFromString(levelString);
			Character *oChar = myChar;
			myChar = nChar;
			delete oChar;

			Level *oLvl = myLvl;
			myLvl = nLvl;
			delete oLvl;	
		}
		else
		{
			atSplash = 3;
			deathScreen->resetTimer();

			// TODO: Destroy and remake the level.
			Level *nLvl = new Level();
			Character *nChar = new Character(0, 0);
			nLvl->setCharacter(nChar);
			nLvl->setGame(this);
			nChar->setGame(this);
			string levelString = loadLevelFile(levelFiles[currentLevel]);
			nLvl->loadFromString(levelString);
			Character *oChar = myChar;
			myChar = nChar;
			delete oChar;

			Level *oLvl = myLvl;
			myLvl = nLvl;
			delete oLvl;
		}	
	}
	if(lComplete)
	{
		lComplete = false;

		atSplash = 2;
		levelClear->resetTimer();

		currentLevel++;
		if(currentLevel > noLevels)
		{
			currentLevel = 1;
			atSplash = 5;
			gameCompleteScreen->resetTimer();
		}

		// TODO: Destroy and remake the level.
		Level *nLvl = new Level();
		Character *nChar = new Character(0, 0);
		nLvl->setCharacter(nChar);
		nLvl->setGame(this);
		nChar->setGame(this);
		string levelString = loadLevelFile(levelFiles[currentLevel]);
		nLvl->loadFromString(levelString);
		
		Character *oChar = myChar;
		myChar = nChar;
		delete oChar;
		
		Level *oLvl = myLvl;
		myLvl = nLvl;
		delete oLvl;	
	}
}

void 
Game::draw(OGLrendrer *ogl)
{
	WaitForSingleObject(ghMutex, INFINITE);
	if(atSplash)
	{
		if(atSplash == 1)
			welcome1->draw(ogl);
		if(atSplash == 2)
			levelClear->draw(ogl);
		if(atSplash == 3)
			deathScreen->draw(ogl);
		if(atSplash == 4)
			gameOverScreen->draw(ogl);
		if(atSplash == 5)
			gameCompleteScreen->draw(ogl);
	}
	else
	{
		if(myLvl)
			myLvl->draw(ogl);
		if(myChar)
			myChar->draw(ogl);
	}
	ReleaseMutex(ghMutex);
}

Character *
Game::getChar()
{
	return myChar;
}

void 
Game::levelComplete()
{
	lComplete = true;
}

string 
Game::loadLevelFile(char *fileName)
{
	string fileBuffer;
	FILE *fHand = fopen(fileName, "r");
	if(fHand)
	{
		fseek(fHand, 0, SEEK_END);
		long fileSize = ftell(fHand);
		fseek(fHand, 0, SEEK_SET);
		char *buffer = new char[fileSize];
		fread(buffer, 1, fileSize, fHand);

		fileBuffer.append(buffer, fileSize);

		delete[] buffer;
		fclose(fHand);
	}
	return fileBuffer;
}

void 
Game::tick()
{
	// Timer tick received.
	if(atSplash)
	{
		if(atSplash == 1)
		{
			welcome1->tick();
			if(welcome1->hasTimerExpired())
				atSplash = 0;
		}
		else if(atSplash == 2)
		{
			levelClear->tick();
			if(levelClear->hasTimerExpired())
				atSplash = 0;
		}
		else if(atSplash == 3)
		{
			deathScreen->tick();
			if(deathScreen->hasTimerExpired())
				atSplash = 0;		
		}
		else if(atSplash == 4)
		{
			gameOverScreen->tick();
			if(gameOverScreen->hasTimerExpired())
				atSplash = 0;		
		}
		else if(atSplash == 5)
		{
			gameCompleteScreen->tick();
			if(gameCompleteScreen->hasTimerExpired())
				atSplash = 0;		
		}
	}
}

void 
Game::keyPress(unsigned int keyPress)
{
	WaitForSingleObject(ghMutex, INFINITE);
		if(keyPress == VK_LEFT)
		{
			myChar->move(1);
			checkState();
		}
		else if(keyPress == VK_RIGHT)
		{
			myChar->move(3);	
			checkState();
		}
		else if(keyPress == VK_UP)
		{
			myChar->move(4);
			checkState();
		}
		else if(keyPress == VK_DOWN)
		{
			myChar->move(2);
			checkState();
		}
		else if(keyPress == VK_SPACE)
		{
			myChar->triggerSquare();
			checkState();
		}
		else if(keyPress == 'P')
		{
			myChar->carryImpulse();
			checkState();			
		}
	ReleaseMutex(ghMutex);
}