#ifndef CHARACTERLIST_H
#define CHARACTERLIST_H

#include "TriggerConfig.h"
#include <STRING>
#include <fstream>
#include <iostream>

 using namespace std;

void swap( CharacterConfig& item1, CharacterConfig& item2 )
{
	
 CharacterConfig temp;
 temp = item1;
 item1 = item2;
 item2 = temp;

 
}

int partition( CharacterConfig* arr[], int first, int last )
{
// cout << "partition called on (" << first << ", " << last << " )" << endl;
 int pivot = arr[first]->CharacterObject.Get_Y();
 int i = first - 1;
 int j = last + 1;
 
 while( i < j )
 {
  do
  {
   j = j - 1;
  } while( arr[j]->CharacterObject.Get_Y() > pivot );

  do
  {
   i = i + 1;
  } while( arr[i]->CharacterObject.Get_Y()< pivot );

  if ( i < j )
	  swap( arr[i], arr[j] );
 }
 return j;
}

void quickSort( CharacterConfig* arr[], int first, int last )
{
	//we want mege sort instean for nlogn every time

textout(screen,font,"quickSort called ",100,220,makecol(6,255,255));
// cout << "quickSort called on (" << first << ", " << last << " )" << endl;
  //displayArray( arr, number_of_items );
	if ( first < last )
 {
  int part = partition( arr, first, last );
  quickSort( arr, first, part );
  quickSort( arr, part + 1, last );
 }
 // else do nothing; array of 1 element is sorted
textout(screen,font,"quickSort done ",100,250,makecol(255,6,255));

}



class CharacterList  
{
	private:
		//CharacterConfig* head;
		CharacterConfig* characterList[maxchars];
		int numItems ;
	public:
		CharacterList();
		//insert at beginning
	
		void load(string);
		void save(string );
		void traverse2( );
		void draw( BITMAP*,int,View);
		bool isEmpty( );
		int GetnumItems( );
		bool IsInList( int );
		int IndexOf( int );
		bool IsInList2( int );
		void insert(string); 
		void setdest();// change to bool
		void setdieolog();
		bool Delete(int d);
		bool Deletec(int d);
		int battle(string);
		bool upDateStats(string);
		int Find_Character_id( int d,int c );
		void setup_collision();
		void sort();
		string listToString(string);
	Character Get_Character( int d );
	

		virtual ~CharacterList();

};




//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CharacterList::CharacterList()
{

	numItems = 0;
}

bool CharacterList::upDateStats(string strings)
{
	
	int j= 0;
	int i = 0;
	//maybey i acn make the conver for sring to char* right in here
	string  temps[12]; //arry to hold data
	
	while (strings[i]!= ',')//'`') //stay in untl you fing the ` at the end riged to find first comma we just want the id
	{
		if (strings[i] != ',')//if found , dont add it to the data and move on to next char
		{
			temps[j] += strings[i]; //add char to temp spot
			i++;
		}
		else
		{
			i++;
			j++;
		}

	}
	///////////////////////////////////////////////////////////////
	for(i=0; i<numItems;i++)
	{
		if( characterList[i]->CharacterObject.Get_id() == StringToNumber(temps[0]) )//Id
		{
		
		characterList[i]->CharacterObject.attributess.Set_statholder(strings);
		characterList[i]->CharacterObject.attributess.fromString();


		//nd->CharacterObject.Set_desty(StringToNumber(temps[2]));//desty
		//nd->CharacterObject.Set_inarea(StringToNumber(temps[3])) //inarea
		}

	}
	/////////////////////////////////////////////////////////////
	
return 1;
}

void CharacterList::insert(string chs )
{

	

	CharacterConfig* nd;
	nd = new CharacterConfig;
	nd->CharacterObject.Set_unit(chs);
	nd->CharacterObject.fromString();
	nd->CharacterObject.Set_destx(nd->CharacterObject.Get_X());
	nd->CharacterObject.Set_desty(nd->CharacterObject.Get_Y());
///////////////////////////////////////////////////////////////////
if (numItems < maxchars)
	{
		characterList[numItems]=nd;
		
	}
////////////////////////////////////////////////////////////////////

	numItems++;
}
///and load from file
void CharacterList::load(string filename )
{

	ifstream inData;
	inData.open(filename.c_str() );
	string namer ;
	char trash ;
	int num = 0;
	int num2 = 0;
			 
	inData >> num;
	inData >> trash;	

	while( 	numItems < num)
  	{

		CharacterConfig* nd;
		nd = new CharacterConfig;

		inData >> namer;
		nd->get_UnitObject()->Set_name(namer);
//characterList[numItems]->CharacterObject.Set_name(namer);
		//inData >> trash;


		inData >> num2;
		if (num2 == 1)
		{
			nd->CharacterObject.Set_race("namakan");
			//characterList[numItems]->CharacterObject.Set_race("namakan");
		}
		inData >> trash;



		inData >> num2;
		if (num2== 1)
		{
			nd->CharacterObject.Set_sex(male);
//characterList[numItems]->CharacterObject.Set_sex(male);
		}
		else if(num2== 2)
		{
			nd->CharacterObject.Set_sex(female);
//characterList[numItems]->CharacterObject.Set_sex(female);
		}
		inData >> trash;


		inData >> num2;
		nd->CharacterObject.Set_X(num2);
//characterList[numItems]->CharacterObject.Set_X(num2);
		inData >> trash;
		//textprintf_centre(screen, font, 40, 200, makecol(255, 255, 255),"FPS:%d", num2);

		inData >> num2;
		nd->CharacterObject.Set_Y(num2);
//characterList[numItems]->CharacterObject.Set_Y(num2);
		inData >> trash;

		inData >> num2;
		nd->CharacterObject.Set_W(num2);
//characterList[numItems]->CharacterObject.Set_W(num2);
		inData >> trash;

		inData >> num2;
		nd->CharacterObject.Set_H(num2);
//characterList[numItems]->CharacterObject.Set_H(num2);
		inData >> trash;

		inData >> num2;
		nd->CharacterObject.Set_layer(num2);
//characterList[numItems]->CharacterObject.Set_layer(num2);
		inData >> trash;

		inData >> num2;
		nd->CharacterObject.Set_source_X(num2);
//characterList[numItems]->CharacterObject.Set_source_X(num2);
		inData >> trash;

		inData >> num2;
		nd->CharacterObject.Set_source_Y(num2);
//characterList[numItems]->CharacterObject.Set_source_Y(num2);
		inData >> trash;

		inData >> num2;
		if (num2== 0)
		{
			nd->CharacterObject.Set_collision(false);
//characterList[numItems]->CharacterObject.Set_collision(false);
		}
		else if (num2== 1)
		{
			nd->CharacterObject.Set_collision(true);
//characterList[numItems]->CharacterObject.Set_collision(true);
		}
		inData >> trash;


		inData >> num2;
		nd->CharacterObject.Set_frame(num2);
//characterList[numItems]->CharacterObject.Set_frame(num2);
		inData >> trash;



		inData >> num2;
		nd->CharacterObject.Set_direction(num2);
//characterList[numItems]->CharacterObject.Set_direction(num2);
		inData >> trash;


		inData >> num2;
		nd->CharacterObject.Set_sourcebitmap(num2);
//characterList[numItems]->CharacterObject.Set_sourcebitmap(num2);
		inData >> trash;


		inData >> num2;
		if (num2== 1)
		{
//characterList[numItems]->CharacterObject.Set_destbitmap();
			//nd->CharacterObject.Set_destbitmap();
		}
		inData >> trash;

		inData >> num2;
		netId ++;
		nd->CharacterObject.Set_id(netId);
//characterList[numItems]->CharacterObject.Set_id(netId);
		inData >> trash;
	
		inData >> num2;
		nd->CharacterObject.Set_inarea(num2);
//characterList[numItems]->CharacterObject.Set_inarea(num2);
		inData >> trash;
	
		inData >> num2;

//characterList[numItems]->CharacterObject.Set_socketid(num2);
//characterList[numItems]->CharacterObject.Set_destx(characterList[numItems]->CharacterObject.Get_X());
//characterList[numItems]->CharacterObject.Set_desty(characterList[numItems]->CharacterObject.Get_Y());
//characterList[numItems]->CharacterObject.toString();

		nd->CharacterObject.Set_socketid(num2);

nd->CharacterObject.Set_destx(nd->CharacterObject.Get_X());
nd->CharacterObject.Set_desty(nd->CharacterObject.Get_Y());
nd->CharacterObject.toString();

textout(screen,font,nd->CharacterObject.Get_unit().c_str(),100,400,makecol(255,255,255));
//
	characterList[numItems]=nd;	
	
		numItems++;
	
	}


	inData.close();

	//Sleep(9000);

}






	



///and save to file
void CharacterList::save( string filename)
{
	CharacterConfig* nd;
//	nd = head;
	
	ofstream outData;
	outData.open(filename.c_str());
	
	outData << numItems;
	outData << ",";
	outData << endl;
	
	//while( nd != NULL ) 
	//{
for(int i=0; i<numItems;i++)
	{
		nd=characterList[i];
		outData << nd->CharacterObject.Get_name();
		outData << endl;
		outData << 1;//nd->CharacterObject.Get_race();
		outData << ",";
		outData << 1;//nd->CharacterObject.Get_sex();
		outData << ",";
		outData << nd->CharacterObject.Get_X();
		outData << ",";
		outData << nd->CharacterObject.Get_Y();
		outData << ",";
		outData << nd->CharacterObject.Get_W();	
		outData << ",";
		outData << nd->CharacterObject.Get_H();
		outData << ",";
		outData << nd->CharacterObject.Get_layer();
		outData << ",";
		outData << nd->CharacterObject.Get_source_X();
		outData << ",";
		outData << nd->CharacterObject.Get_source_Y();	
		outData << ",";
		outData << 0; //nd->CharacterObject.Is_in_collision();
		outData << ",";
		outData << nd->CharacterObject.Get_frame();
		outData << ",";
		outData << 1 ;//nd->CharacterObject.Get_direction()
		outData << ",";
		outData << nd->CharacterObject.Get_sourcebitmap();
		outData << ",";
		outData << 2;//nd->CharacterObject.Get_destbitmap();
		outData << ",";
		outData << nd->CharacterObject.Get_id();
		outData << ",";
		outData << nd->CharacterObject.Get_inarea();
		outData << ",";
		outData << nd->CharacterObject.Get_socketid();
		outData << endl;
		
	

	}
	
	
	outData.close();
	
}
////

void CharacterList::setup_collision()
{
	if(debugmode==true)
{
	textout(screen,font,"setup_collision called ",100,320,makecol(6,255,255));
	}
	
	int i,j;
	
	for(  i = 0; i < numItems; i++ )
	{
	 
		for(  j = 0; j < numItems; j++ )
		{
			if(characterList[i]->CharacterObject.Get_inarea()== characterList[j]->CharacterObject.Get_inarea())
			{
				if(characterList[i]->CharacterObject.is_collision(characterList[j]->get_UnitObject()) )
				{
					if(characterList[i]->CharacterObject.Get_id() != characterList[j]->CharacterObject.Get_id())
					{
						textout(screen,font," collision detected ",400,320,makecol(6,255,255));

						characterList[i]->CharacterObject.Set_collision(true);
						characterList[j]->CharacterObject.Set_collision(true);
				
					}
					else
					{
						characterList[i]->CharacterObject.Set_collision(false);
			
					}
				}
				else
				{
					characterList[i]->CharacterObject.Set_collision(false);

				}
			}
		
		}	
	
	}
if(debugmode==true)
{
	textout(screen,font,"setup_collision done ",100,350,makecol(255,6,255));
}
}




void CharacterList::traverse2( )
{
	CharacterConfig* nd;
	
	
	for( int i = 0; i < numItems; i++ )
	{
		nd = characterList[i];
		
	}
	
}
void CharacterList::sort()
{
//first we need to sorut by x lesest to greatest
quickSort(characterList,0,numItems-1);
}
void CharacterList::draw(BITMAP* bmp,int lay,View v )
{


	

for( int i = 0; i < numItems; i++ )
	{
	if(characterList[i]->CharacterObject.Get_inarea() == current_area)
	{
		if (characterList[i]->CharacterObject.Get_layer()== lay)
		{	
			
			characterList[i]->CharacterObject.do_moveing();
			characterList[i]->CharacterObject.animate();
			characterList[i]->CharacterObject.draw(bmp,v);
			characterList[i]->CharacterObject.showname(bmp,v);
			characterList[i]->CharacterObject.showlife(bmp,v);
			characterList[i]->CharacterObject.talk(bmp,v);
		}
	}
		
	}



}

bool CharacterList::isEmpty( )
{
	return( numItems == 0 );
}

int CharacterList::GetnumItems( )
{
	return numItems;
}

bool CharacterList::IsInList( int d )
{
	//CharacterConfig* nd;
	//nd = head;
//	while( nd != NULL )
for( int i = 0; i < numItems; i++ )
	
	{
		if( characterList[i]->CharacterObject.Get_id() == d )
		{
			return true;
		}
			//nd = nd->GetNext( );
	}
	return false;
}

void CharacterList::setdest()
{

	int j= 0;
	int i = 0;
	//maybey i acn make the conver for sring to char* right in here
	string temps[8]; //arry to hold data
	
	while (movestring[i]!= '`') //stay in untl you fing the ` at the end
	{
		if (movestring[i] != ',')//if found , dont add it to the data and move on to next char
		{
			temps[j] += movestring[i]; //add char to temp spot
			i++;
		}
		else
		{
			i++;
			j++;
		}

	}

	CharacterConfig* nd;
//	nd = head;
	
	//while( nd != NULL )
	//{
for(  i = 0; i < numItems; i++ )
	{
nd=characterList[i];
		if( nd->CharacterObject.Get_id() == StringToNumber(temps[0]) )//Id
		{
		nd->CharacterObject.Set_X(StringToNumber(temps[3]));//curent x
		nd->CharacterObject.Set_Y(StringToNumber(temps[4]));//curent y
		nd->CharacterObject.Set_destx(StringToNumber(temps[1])); //destx
		nd->CharacterObject.Set_desty(StringToNumber(temps[2]));//desty
		
		nd->CharacterObject.Set_direction(StringToNumber(temps[5]));//curent dirfacing
		nd->CharacterObject.Set_frame(StringToNumber(temps[6])); //current frame
		//nd->CharacterObject.Set_inarea(StringToNumber(temps[3])) //inarea
		break;//if found stop looking
		}
		//	nd = nd->GetNext( );
			
	}

}
void CharacterList::setdieolog()
{

	int j= 0;
	int i = 0;
	//maybey i acn make the conver for sring to char* right in here
	string temps[3]; //arry to hold data
	
	while (talkstring[i]!= '`') //stay in untl you fing the ` at the end
	{
		if (talkstring[i] != ',')//if found , dont add it to the data and move on to next char
		{
			temps[j] += talkstring[i]; //add char to temp spot
			i++;
		}
		else
		{
			i++;
			j++;
		}

	}

if (StringToNumber(temps[0]) == 0)
{
serverdiolog = temps[1];
}
else
{

	CharacterConfig* nd;
//	nd = head;
	int index = 0;
//	while( nd != NULL )
	//{
for( i=0; i<numItems;i++)
	{
 nd= characterList[i];
		if( nd->CharacterObject.Get_id() == StringToNumber(temps[0]) )//Id
		{
		
		nd->CharacterObject.Set_dieolog(temps[1]); 
nd->CharacterObject.msglife = 0;

//nd->CharacterObject.msgdie = xt +5;
		break; //stop looking when found
		}
		//	nd = nd->GetNext( );
			
	}
}
}

int CharacterList::IndexOf( int d )
{
for( int i = 0; i < numItems; i++ )
	{
		
if( characterList[i]->CharacterObject.Get_id() == d )
		{
		//nd = nd->GetNext();
	return i;
}
	}
	
	return -1;
}



Character CharacterList::Get_Character( int d )
{

	//notfoun need log error
for( int i = 0; i < numItems; i++ )
	{
		
		if( characterList[i]->CharacterObject.Get_id() == d )
		{
		//nd = nd->GetNext();
			return characterList[i]->CharacterObject;
		}
	}
	return Character();
}





int CharacterList::Find_Character_id( int d ,int c)
{
	/*
	CharacterConfig* nd;
	//nd = head;
	int index = 0;
	
	while( nd != NULL )
	{
		
		if( nd->CharacterObject.Get_id() == d )
		{

			if (c == 1)
			{
			nd->CharacterObject.Set_corrent_frame(nd->CharacterObject.Get_frame2());

			}
			else if(c == 2)
			{
			nd->CharacterObject.Set_corrent_frame(nd->CharacterObject.Get_frame3());

			}
			else if(c == 3)
			{
			nd->animeObject.Set_corrent_frame(nd->animeObject.Get_frame4());

			}
			else if(c == 4)
			{
			nd->animeObject.Set_corrent_frame(nd->animeObject.Get_frame5());

			}
			else 
			{
			nd->animeObject.Set_corrent_frame(nd->animeObject.Get_frame1());

			}

			return nd->CharacterObject.Get_corrent_frame();
			break;
			
		}
	//	nd = nd->GetNext( );
		index++;
	}
*/
	return -1;
}


bool CharacterList::Delete(int d)
{

	int i;
	for( i=0; i<numItems;i++)
	{
		if(characterList[i]->CharacterObject.Get_id()==d)
		{
			swap(characterList[i]->CharacterObject,characterList[numItems-1]->CharacterObject);
			numItems--;
	
			return true;
		}
	}

	return false;
}


bool CharacterList::Deletec(int d)
{

	int i;
	for( i=0; i<numItems;i++)
	{
		if(characterList[i]->CharacterObject.Get_socketid()==d)
		{
			swap(characterList[i]->CharacterObject,characterList[numItems-1]->CharacterObject);
			numItems--;
			return true;
		}
	}


return false;
}

string CharacterList::listToString(string d)
{
CharacterConfig* nd;
//	nd = head;
	string list="";
loding += (numItems * 2) + 1;
	for( int i = 0; i < numItems; i++ )
	{
nd=characterList[i];
textout(screen,font,(nd->CharacterObject.toString()).c_str(),100,300,makecol(255,255,255));
//Sleep(10000);
		outboxbuffer += d+"|0|004|"+ (nd->CharacterObject.toString()) +'~';
		//textout(screen,font,(nd->CharacterObject.attributess.toString()).c_str(),10,400,makecol(255,255,255));
//Sleep(10000);
		outboxbuffer += d+"|0|009|"+NumberToString((nd->CharacterObject.Get_id())) +','+ (nd->CharacterObject.attributess.toString()) +'~';
		list += nd->CharacterObject.toString() + '~';
		//nd = nd->GetNext();
	}
//textout(screen,font,outboxbuffer.c_str(),-250,300,makecol(255,255,255));
//
	return list;
}

int CharacterList::battle(string bat)
{
	int j= 0;
	int i = 0;
//maybey i acn make the conver for sring to char* right in here
	string temps[2]; //arry to hold data
	
	while (bat[i]!= '`') //stay in untl you fing the ` at the end
	{
		if (bat[i] != ',')//if found , dont add it to the data and move on to next char
		{
			temps[j] += bat[i]; //add char to temp spot
			i++;
		}
		else
		{
			i++;
			j++;
		}

	}



	int attacker_id = StringToNumber(temps[0]); 
	int defender_id = StringToNumber(temps[1]);
	
	bool attacker_found = false, defender_found = false;

	int attacker,defender;

	for(  attacker = 0; attacker < numItems; attacker++ )
	{
		
		if( characterList[attacker]->CharacterObject.Get_id() == attacker_id )
		{
			
			attacker_found = true;
			break;
		}

	}

	for(  defender= 0; defender < numItems; defender++ )
	{
		
		if( characterList[defender]->CharacterObject.Get_id() ==defender_id )
		{
		
			defender_found = true;
			break;
		}
	}

		if ((attacker_found == true) && (defender_found == true))
		{
			if(characterList[defender]->CharacterObject.Is_in_collision()==1 && characterList[attacker]->CharacterObject.Is_in_collision()==1 )
			{

					characterList[attacker]->CharacterObject.attack(&characterList[defender]->CharacterObject);
			}
			else
			{
				outboxbuffer +=attacker_id +"|0|003|" + NumberToString(computerId) + ",you or your tager is not in collision`~";
			}

		}
		else
		{
		outboxbuffer +=attacker_id +"|0|003|" + NumberToString(computerId) + ",cant find traget`~";
		return -1;
		}


return 0;	
}

CharacterList::~CharacterList()
{

}


#endif