#include "Grid.h"
#include <string>
#include <cmath>
#include <ctime>
//*************************************
//
//Created by Clauda Ephrem   Date Jan 3, 2008
//
// 
//*************************************
using namespace std;

int Grid::getTotalPopulation()
{
	return gridPopulation.countNaiveCooperator + gridPopulation.countNaiveDefector +
		gridPopulation.countPavlov + gridPopulation.countWAC + gridPopulation.countTFT +
		gridPopulation.countWAD;
}


Patch* Grid::getDestination(Patch *InitialLocation, int Movedistance)
{
	int rdDirection = rand()%360;
	int xmvt = (int) floor(cos(( rdDirection *PI)/180.0));
	int ymvt = (int) floor(sin(( rdDirection *PI)/180.0));

	int newXCoordinate = InitialLocation->getXCoordinate() + xmvt;
	int newYCoordinate = InitialLocation->getYCoordinate() + ymvt;

	switch (currentTopology)
	{
	case Torus:
		if (newXCoordinate >= width)
			newXCoordinate = newXCoordinate %width;
		else if (newXCoordinate < 0)
			newXCoordinate = newXCoordinate + width;
		if (newYCoordinate >= height)
			newYCoordinate = newYCoordinate %height;
		else if (newYCoordinate < 0)
			newYCoordinate = newYCoordinate + height;
		break;
	case Bounce: // need to decide bounce in what direction?
				if (newXCoordinate >= width)
			newXCoordinate = newXCoordinate %width;
		else if (newXCoordinate < 0)
			newXCoordinate = newXCoordinate + width;
		if (newYCoordinate >= height)
			newYCoordinate = newYCoordinate %height;
		else if (newYCoordinate < 0)
			newYCoordinate = newYCoordinate + height;
		break;
		
	case Stick:
		if (newXCoordinate >= width)
			newXCoordinate = width-1;
		else if (newXCoordinate < 0)
			newXCoordinate = 0;
		if (newYCoordinate >= height)
			newYCoordinate = height - 1;
		else if (newYCoordinate < 0)
			newYCoordinate = 0;
		break;
	default:
				if (newXCoordinate >= width)
			newXCoordinate = newXCoordinate %width;
		else if (newXCoordinate < 0)
			newXCoordinate = newXCoordinate + width;
		if (newYCoordinate >= height)
			newYCoordinate = newYCoordinate %width;
		else if (newYCoordinate < 0)
			newYCoordinate = newYCoordinate + width;



	}
	
	return arrayOfPatches[newYCoordinate][newXCoordinate];
}

void Grid::getPopulationBreakdown(ostream& output)
{
	output << gridPopulation.countNaiveCooperator << "," << 
			gridPopulation.countNaiveDefector << "," <<
			gridPopulation.countPavlov << "," << 
			gridPopulation.countTFT << "," << 
			gridPopulation.countWAC <<  "," << gridPopulation.countWAD <<endl;

}

int Grid::getSubPopulation(Strategy strategy)
{
	switch(strategy)
	{
	case NaiveCooperator:
		return gridPopulation.countNaiveCooperator;
		break;
	case NaiveDefector:
		return gridPopulation.countNaiveDefector;
		break;
	case Pavlov:
		return gridPopulation.countPavlov;
		break;
	case TFT:
		return gridPopulation.countTFT;
		break;
	case WAC:
		return gridPopulation.countWAC;
		break;
	case WAD:
		return gridPopulation.countWAD;
		break;
	default:
		cout<<"STH is wrong with the strategy specified"<<endl;
		return 0;
		break;
	};
}

Grid::Grid(int Height, int Width, int NbOfSpecies, Topology top, PopulationTable& pop)
{
	gridPopulation = pop;
	height = Height;
	width = Width;
	nbSpeciesOfInterest = NbOfSpecies;
	currentTopology = top;
	arrayOfPatches = new Patch**[height];

	for (int rows = 0 ; rows < height ; rows ++)
	{
		arrayOfPatches[rows] = new Patch*[width];
		for (int col = 0 ; col< width ; col++)
		{
			arrayOfPatches[rows][col] = new Patch(col, rows);

		}
	}
}


Patch* Grid::getRandomDestination ()
{
	//time_t t = time(NULL);
	int rdabs = rand()%width;
	int rdord = (rand()+rand())%height;

	return arrayOfPatches[rdord][rdabs];
}
Grid::Grid()
{
}