#include "StdAfx.h"
#include "Level.h"

#include "Block.h"
#include "FirmBlock.h"
#include "FragileBlock.h"
#include "IceBlock.h"
#include "SlotBlock.h"
#include "Bomb.h"
#include "Character.h"
#include "Game.h"

bool isIn(char needle, char *hayStack)
{
	int len = strlen(hayStack);
	for(unsigned int i=0 ; i!=len ; i++)
	{
		if(needle == hayStack[i])
			return true;
	}
	return false;
}

Level::Level(void)
{
	startingX = 0;
	startingY = 0;

	bombsLeft = 0;
	/*
	nBlock = new FragileBlock(1, 0);
	blockStore.push_back(nBlock);




	nBlock = new FirmBlock(0, 1);
	Bomb *nBomb = new Bomb(1, 0, 1);
	nBlock->addBomb(nBomb);
	blockStore.push_back(nBlock);

	nBlock = new FirmBlock(0, 2);
	nBomb = new Bomb(2, 0, 2);
	nBlock->addBomb(nBomb);
	blockStore.push_back(nBlock);

	nBlock = new FirmBlock(0, 3);
	nBomb = new Bomb(3, 0, 3);
	nBlock->addBomb(nBomb);
	blockStore.push_back(nBlock);*/
}


Level::~Level(void)
{
	list<Block *>::iterator blockIter = blockStore.begin();
	for(; blockIter!=blockStore.end() ; blockIter++)
	{
		delete *blockIter;
	}
}


void 
Level::draw(OGLrendrer *ogl)
{
	list<Block*>::iterator blockIter = blockStore.begin();
	for(; blockIter!=blockStore.end() ; blockIter++)
	{
		(*blockIter)->draw(ogl);
	}
}

void 
Level::removeBlock(Block *a)
{
	list<Block*>::iterator blockIter = blockStore.begin();
	for(; blockIter!=blockStore.end() ; blockIter++)
	{
		if((*blockIter) == a)
		{
			blockStore.erase(blockIter);
			break;
		}
	}
}

Block *
Level::getBlock(int x_, int y_)
{
	list<Block*>::iterator blockIter = blockStore.begin();
	for(; blockIter!=blockStore.end() ; blockIter++)
	{
		int blockX;
		int blockY;
		(*blockIter)->getCoords(&blockX, &blockY);
		if((blockX == x_) && (blockY == y_))
		{
			return *blockIter;
		}
	}
	return NULL;
}

void 
Level::triggerExplosive(int x, int y)
{
	Block *thisBlock = getBlock(x, y);
	if(thisBlock)
	{
		thisBlock->fireBomb();	
	}
}

Character *
Level::getCharacter()
{
	return associatedCharacter;
}

void 
Level::setCharacter(Character *a)
{
	associatedCharacter = a;
}

void 
Level::removeBomb()
{
	bombsLeft--;

	if(bombsLeft == 0)
		completeLevel();
}

void 
Level::setGame(Game *a)
{
	associatedGame = a;
}

void 
Level::completeLevel()
{
	associatedGame->levelComplete();
}

void 
Level::loadFromString(string &a)
{
	char buffer[1024];
	unsigned int bufInd = 0;
	unsigned int i = 0;
	while((i < a.length()) && (a[i] == '('))
	{
		i += loadBlockFromString(a, i);
	}
}

unsigned int
Level::loadBlockFromString(string &a, unsigned int index)
{
	unsigned int i = index;
	char buffer[1024];
	unsigned int bufInd = 0;
	Block *nBlock = NULL;
	i++;
	memset(buffer, 0, 1024);
	while(isIn(a[i], "-0123456789"))
	{
		buffer[bufInd] = a[i];
		bufInd++;
		i++;
	}
	while(a[i] == ',')
	{
		i++;
	}
	int newTileX = atoi(buffer);
	memset(buffer, 0, 1024);
	bufInd = 0;
	while(isIn(a[i], "-0123456789"))
	{
		buffer[bufInd] = a[i];
		bufInd++;
		i++;
	}
	while(a[i] == ',')
	{
		i++;
	}
	int newTileY = atoi(buffer);
	memset(buffer, 0, 1024);
	bufInd = 0;
	while(isIn(a[i], "FICS"))
	{
		if(a[i] == 'F')
		{
			nBlock = new FragileBlock(newTileX, newTileY);
		}
		else if(a[i] == 'I')
		{
			nBlock = new FirmBlock(newTileX, newTileY);
		}
		else if(a[i] == 'C')
		{
			nBlock = new IceBlock(newTileX, newTileY);
		}
		else if(a[i] == 'S')
		{
			nBlock = new SlotBlock(newTileX, newTileY);
		}
 		blockStore.push_back(nBlock);
		i++;
	}

	if(a[i] == ')')
	{
		i++;
		return i-index;
	}
	else if(a[i] == ',')
		i++;

	i += loadDecorations(a, i, nBlock);
	if(a[i] == ')')
	{
		i++;
	}
	return i-index;
}

unsigned int 
Level::loadDecorations(string &a, unsigned int index, Block *nBlock)
{
	unsigned int i = 0;
	while(isIn(a[index+i], "B123P"))
	{
		if(a[index+i] == 'P')
		{
			i++;
			// This square is the level's starting square.
		}
		else if(a[index+i] == 'B')
		{
			i += loadBomb(a, index+i, nBlock);
		}
	}
	return i;
}

unsigned int 
Level::loadBomb(string &a, unsigned int index, Block *nBlock)
{
	unsigned int i = 0;
	if(a[index+i] == 'B')
	{
		i++;

		// Tile has a bomb. 
		Bomb *nBomb = NULL;
		int bombX, bombY;
		nBlock->getCoords(&bombX, &bombY);
		if(a[index+i] == '1')
		{
			nBomb = new Bomb(1, bombX, bombY);
			i++;
		}
		else if(a[index+i] == '2')
		{
			nBomb = new Bomb(2, bombX, bombY);
			i++;
		}
		else
		{
			nBomb = new Bomb(3, bombX, bombY);
			i++;
		}
		nBomb->setLevel(this);
		nBlock->addBomb(nBomb);	
		bombsLeft++;
	}
	return i;
}