#include "AgentIndex.h"
#include "Agent.h"
#include "Patch.h"
#include <fstream>
//*************************
//
//Created by Clauda Ephrem		Date Jan 3, 2008
//
//Edited by Vivian Jreig		Date March 25, 2008
//void AgentIndex::Remove(int AgentLocation)
//Edited by Clauda Ephrem		Date April 10, 2008
//added the function: void AgentIndex::getAgentsInfo(ofstream& outfile)
//
//*************************
using namespace std;

AgentIndex::AgentIndex(int population )
{
	FirstVacant = 0;
	LastTouched = 0;
	IndexBody = new IndexEntry[2*population];
}

Agent* AgentIndex::GetLastTouched()
{
	Agent* TempAgent = new Agent(1);
	IndexEntry TempElement;

	if (LastTouched > FirstVacant-1)
	{
		LastTouched = 0;
	}
	TempElement= IndexBody[LastTouched];
	
	TempAgent = TempElement.pAgent;
	
	if (TempAgent->getCurrentPartner() !=NULL)
	{

		MoveBefore (TempAgent->getCurrentPartner()->getIndexLocation() , LastTouched);
	}
	LastTouched = TempElement.Next;
	
	return TempElement.pAgent;
}

Agent* AgentIndex::GetRandomAgent()
{
	int rd = rand()%(FirstVacant);
	return IndexBody[rd].pAgent;
}

void AgentIndex::Insert(Agent *NewAgent)
{

	NewAgent->IndexLocation = FirstVacant;

	if (FirstVacant == 0)
	{
		IndexBody[FirstVacant].pAgent = NewAgent;
		IndexBody[FirstVacant].Next = FirstVacant;
		IndexBody[FirstVacant].Previous = FirstVacant;
	
	}
	else
	{
		IndexBody[FirstVacant].pAgent = NewAgent;

		MoveBefore(FirstVacant, LastTouched);

	}
	FirstVacant++;

}

void AgentIndex::MoveBefore(int a, int b)
{
	int temp;
	if (a == b)
	{
		return;
	}

	if ( FirstVacant == 1 && a == 1)

	{
		IndexBody[a].Next = b;
		IndexBody[a].Previous = b;
		IndexBody[b].Next = a;
		IndexBody[b].Previous = a;
	}
	else
		{

		if (IndexBody[b].Previous == a )
		{

			return;
		}
		if(IndexBody[a].Previous == b && IndexBody[a].Next == b)
		{
			return;
		}
		if (IndexBody[a].Previous != -1 && IndexBody[a].Next != -1)
		{

			temp = IndexBody[b].Previous;
			IndexBody[IndexBody[a].Previous].Next = IndexBody[a].Next;
			IndexBody[IndexBody[a].Next].Previous = IndexBody[a].Previous;

			IndexBody[IndexBody[b].Previous].Next = a;
			IndexBody[b].Previous = a;
			IndexBody[a].Next = b;
			IndexBody[a].Previous = temp;
		}
		else
		{
			temp = IndexBody[b].Previous;
			IndexBody[temp].Next = a;
			IndexBody[b].Previous = a;
			IndexBody[a].Next = b;
			IndexBody[a].Previous = temp;
		}
	}

}
//***** added if last touched= frist vacant - 1 then let LastTouched= IndexBody [FirstVacant-1].Next ****
void AgentIndex::Remove(int AgentLocation)
{

	if(LastTouched == FirstVacant-1)
		LastTouched = IndexBody[FirstVacant-1].Next;
	
	Swap (AgentLocation, FirstVacant-1);
	
	IndexBody[IndexBody[FirstVacant-1].Previous].Next =IndexBody[FirstVacant-1].Next;
	IndexBody[IndexBody[FirstVacant-1].Next].Previous =IndexBody[FirstVacant-1].Previous;
	IndexBody[FirstVacant-1].pAgent->getphCurrentLocation()->Agent_departing(IndexBody[FirstVacant-1].pAgent);
	IndexBody[FirstVacant-1].pAgent = NULL;
	IndexBody[FirstVacant-1].Previous=-1;
	IndexBody[FirstVacant-1].Next=-1;
	FirstVacant--;

}

void AgentIndex::Swap(int a, int b)
{
	Agent* temp = new Agent(1);
	temp = IndexBody[a].pAgent;
	IndexBody[a].pAgent = IndexBody[b].pAgent;
	IndexBody[b].pAgent = temp;
	IndexBody[a].pAgent->SetIndexLocation (a);
	IndexBody[b].pAgent->SetIndexLocation (b);
}

//**** Prints to a log file each agent's ID, current partner, curretn location, etc
void AgentIndex::getAgentsInfo(ofstream& outfile)
{
	outfile<<"State Dumo:"<<endl;
		
	for (int i=0; i<FirstVacant; i++)
	{	outfile<<1+i<<": ",
		IndexBody[i].pAgent->printState(outfile);
	}	
}



