//Corporate Structure

//NOTE: the serialization code was mirrored from the Salvage Manager

/*   
	--serializing order--

int   m_iSponsorRegiment;
int   m_iSolarisTitle;
int   m_iCurrentStatus;
int   m_iDate;
int   m_iMissionVictoryCount;
int   m_iMissionDefeatCount;
int   m_iPlayerMechKills;
int   m_iLanceMechKills;

int   m_aiArenaVictoryCount[NUM_OF_ARENAS];
int   m_aiArenaDefeatCount[NUM_OF_ARENAS];

count
std::vector<int>   m_unitStrength;
count
std::vector<int>   m_infamy;
count
std::vector<int>   m_steinerFactionRating;
count
std::vector<int>   m_davionFactionRating;
count
std::vector<int>   m_nobility;

Stuff::MString  m_szCompanyName;

*/



#include "MW4Headers.hpp"
#include "MWCorporation.hpp"
#include "MWGame.hpp"
#include "MWApplication.hpp"
#include "MWTable.hpp"
#include "Salvage.hpp"
#include "Mech.hpp"
#include "SubsystemClassData.hpp"
#include "Weapon.hpp"

#include <Stuff\Stuff.hpp> //for the MString

//#include "..\buildnum\buildnum.h" //no idea why -- salvage does it

#include "..\Content\Mercenaries\scriptstrings.h"

#include <Adept\Tool.hpp>



//Stuff
MWCorporation::ClassData*
	MWCorporation::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWCorporation::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MWCorporationClassID,
			"MechWarrior4::MWCorporation",
			Receiver::DefaultData,
			0,
			NULL
		);
	Check_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWCorporation::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}


//++*++ Contstructor(s)

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MWCorporation::MWCorporation (Stuff::MemoryStream *stream) : 
	Receiver(DefaultData),
	dwFlags(0),
	m_iSponsorRegiment(0),
	m_iSolarisTitle(0),
	m_iCurrentStatus(0),
	m_iDate(0),
	m_iMissionVictoryCount(0),
	m_iMissionDefeatCount(0),
	m_iPlayerMechKills(0),
	m_iLanceMechKills(0) 
{ 
	//De-Serialize the data
	if(stream)
	{
		int count;
		int temp;
		
		Check_Pointer(stream);


		*stream >> m_iSponsorRegiment;     // int 
		*stream >> m_iSolarisTitle;        // int 
		*stream >> m_iCurrentStatus;       // int 
		*stream >> m_iDate;                // int 
		*stream >> m_iMissionVictoryCount; // int 
		*stream >> m_iMissionDefeatCount;  // int
		*stream >> m_iPlayerMechKills;     // int
		*stream >> m_iLanceMechKills;      // int

		for(int i=0; i<NUM_OF_ARENAS; i++)
		{
			*stream >> temp;
			m_aiArenaVictoryCount[i] = temp;
			*stream >> temp;
			m_aiArenaDefeatCount[i] = temp;
		}


		*stream >> count;
		while (count--)
		{
			*stream >> temp;
			MWCorporation::m_unitStrength.push_back(temp);
		}
		*stream >> count;
		while (count--)
		{
			*stream >> temp;
			MWCorporation::m_infamy.push_back(temp);
		}
		*stream >> count;
		while (count--)
		{
			*stream >> temp;
			MWCorporation::m_steinerFactionRating.push_back(temp);
		}
		*stream >> count;
		while (count--)
		{
			*stream >> temp;
			MWCorporation::m_davionFactionRating.push_back(temp);
		}
		*stream >> count;
		while (count--)
		{
			*stream >> temp;
			MWCorporation::m_nobility.push_back(temp);
		}

		while(stream->GetBytesRemaining() > 0) //I think this gets one byte at a time -- dont think i need to do this
		{
			MString company_name;
			*stream >> MWCorporation::m_szCompanyName;
		}
	}
}


  
//++*++ Destructor(s)

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWCorporation::~MWCorporation () 
{ 
	//empty
}


//++*++ Serialization

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MWCorporation *MWCorporation::MakeNewCorporation(const ResourceID& corporation_resource_id)
{
	MWCorporation *new_corporation;
	if(corporation_resource_id != ResourceID::Null)
	{
		Resource corporation_resource(corporation_resource_id);
		Verify(corporation_resource.DoesResourceExist());
		corporation_resource.LoadData();
		
		new_corporation = new MWCorporation(&corporation_resource);
		Check_Object(new_corporation);
	}
	else
		new_corporation = new MWCorporation(NULL);

	return new_corporation;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MWCorporation *MWCorporation::MakeNewCorporation(const char *corporation_name)
{

	MWCorporation *new_corporation;

	Resource corporation_resource(corporation_name);
	if(corporation_resource.DoesResourceExist())
	{
		corporation_resource.LoadData();
		new_corporation = new MWCorporation(&corporation_resource);
		Check_Object(new_corporation);
	}
	else
		new_corporation = new MWCorporation(NULL);

	return new_corporation;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MWCorporation::ConstructCorporationStream(MemoryStream *stream)
{
	Check_Pointer(stream);

	int dummyZero = 0;
	*stream << dummyZero;  // int m_iSponsorRegiment
	*stream << dummyZero;  // int m_iSolarisTitle
	*stream << dummyZero;  // int m_iCurrentStatus
	*stream << dummyZero;  // int m_iDate
	*stream << dummyZero;  // int m_iMissionVictoryCount
	*stream << dummyZero;  // int m_iMissionDefeatCount
	*stream << dummyZero;  // int m_iPlayerMechKills
	*stream << dummyZero;  // int m_iLanceMechKills

	int i;
	for (i=0; i<NUM_OF_ARENAS; i++)
	{
		*stream << dummyZero;  // m_aiArenaVictoryCount[i] -- where i==The Arena Index
		*stream << dummyZero;  // m_aiArenaDefeatCount[i] -- where i==The Arena Index
	}

	*stream << dummyZero; //count
	// m_unitStrength -- but there are 0 of these being stored
	*stream << dummyZero; //count
	// m_infamy -- but there are 0 of these being stored
	*stream << dummyZero; //count
	// m_steinerFactionRating -- but there are 0 of these being stored
	*stream << dummyZero; //count
	// m_davionFactionRating -- but there are 0 of these being stored
	*stream << dummyZero; //count
	// m_nobility -- but there are 0 of these being stored

	Stuff::MString dummyString = "X-Northwind Highlanders-X";
	*stream << dummyString;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MWCorporation::Save(MemoryStream *stream)
{
	Check_Object(this);
	Check_Pointer(stream);

	*stream << m_iSponsorRegiment;      // int
	*stream << m_iSolarisTitle;         // int
	*stream << m_iCurrentStatus;        // int
	*stream << m_iDate;                 // int
	*stream << m_iMissionVictoryCount;  // int
	*stream << m_iMissionDefeatCount;   // int
	*stream << m_iPlayerMechKills;      // int
	*stream << m_iLanceMechKills;       // int

	int i;
	for (i=0; i<NUM_OF_ARENAS; i++)
	{
		*stream << m_aiArenaVictoryCount[i];      // int
		*stream << m_aiArenaDefeatCount[i];       // int
	}

	int count;
	count = MWCorporation::m_unitStrength.size();
	*stream << count;

	i=0;
	while (i<count)
	{
		*stream << MWCorporation::m_unitStrength[i++];
	}

	count = MWCorporation::m_infamy.size();
	*stream << count;

	i=0;
	while (i<count)
	{
		*stream << MWCorporation::m_infamy[i++];
	}

	count = MWCorporation::m_steinerFactionRating.size();
	*stream << count;

	i=0;
	while (i<count)
	{
		*stream << MWCorporation::m_steinerFactionRating[i++];
	}

	count = MWCorporation::m_davionFactionRating.size();
	*stream << count;

	i=0;
	while (i<count)
	{
		*stream << MWCorporation::m_davionFactionRating[i++];
	}

	count = MWCorporation::m_nobility.size();
	*stream << count;

	i=0;
	while (i<count)
	{
		*stream << MWCorporation::m_nobility[i++];
	}

	*stream << MWCorporation::m_szCompanyName;

	return;
}



//++*++ Non-Trivial Get Methods

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::GetCurrentUnitStrength (void) 
{ 
	if ((MWCorporation::dwFlags & MWCORPORATION_UNIT_STRENGTH_VALID) != MWCORPORATION_UNIT_STRENGTH_VALID)
		return -1; //FAILURE

	return MWCorporation::m_unitStrength[MWCorporation::m_iDate]; 
} 

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::GetCurrentInfamy (void) 
{
	if ((MWCorporation::dwFlags & MWCORPORATION_INFAMY_VALID) != MWCORPORATION_INFAMY_VALID)
		return -1; //Failure -- not set yet

	return MWCorporation::m_infamy[MWCorporation::m_iDate]; 
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::GetCurrentSteinerFactionRating (void) 
{ 
	if ((MWCorporation::dwFlags & MWCORPORATION_STEINER_RATING_VALID) != MWCORPORATION_STEINER_RATING_VALID)
		return -1; //Failure -- not set yet

	return MWCorporation::m_steinerFactionRating[MWCorporation::m_iDate]; 
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::GetCurrentDavionFactionRating (void) 
{ 
	if ((MWCorporation::dwFlags & MWCORPORATION_DAVION_RATING_VALID) != MWCORPORATION_DAVION_RATING_VALID)
		return -1; //Failure -- not set yet

	return MWCorporation::m_davionFactionRating[MWCorporation::m_iDate]; 
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::GetCurrentNobility (void)
{
	if ((MWCorporation::dwFlags & MWCORPORATION_NOBILITY_VALID) != MWCORPORATION_NOBILITY_VALID)
		return -1; //Failure -- not set yet

	return MWCorporation::m_nobility[MWCorporation::m_iDate]; 
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


//Costs for current cycle -- some percentage of the sum of your dragoon ratings
int MWCorporation::GetCycleExpenses (void)
{
	//I need the m_mechTable from MWGame -- NOT MWApplication
	int totalMechValues = 0; //MoneyType
	int i; //counter
	Check_Object(MWGame::GetInstance());

	MWGame *game = MWGame::GetInstance();
	game->m_blackMarketManager;
	MWApplication *app = MWApplication::GetInstance();
	MWGame *gamez = MWGame::GetInstance();
	app->m_mechTable;
	gamez->m_mechTable;

	Stuff::SortedChainIteratorOf <MechTablePlug *, Stuff::MString> mech_iterator (&MWGame::GetInstance()->m_mechTable);

	MechTablePlug *mech_plug;
	Resource model_resource;
	//cycle through the mech table of company owned mechs
	while((mech_plug = mech_iterator.ReadAndNext()) != NULL)
	{
		Check_Object(mech_plug);

		if ((MWApplication::GetInstance()) && (MWGame::GetInstance()))
		{
			Stuff::MString basic_name = mech_plug->GetOriginalName(); //with all numbers stripped from the original name
			//strip the numbers
			for (i=0; i<basic_name.GetLength(); i++)
			{
				if (basic_name[i] < 'A')
				{
					basic_name[i] = '\0';
					break;
				}
			}

			//Find the mech from the MWGame's mechTable in the MWApplication's mechTable to get its tradeValue
			MWTableEntry *mech_entry = MWApplication::GetInstance()->m_mechTable->FindEntry(basic_name);
			Check_Object(mech_entry);

			Resource mech_resource(mech_entry->GetEntryResourceID());
			Verify(mech_resource.DoesResourceExist());

			Mech::CreateMessage *mech_create_message;
			mech_create_message = Cast_Pointer(Mech::CreateMessage *, mech_resource.GetPointer());
			Resource model_resource;
			Entity::GetGameModelResourceFromDataListID(&model_resource, mech_create_message->dataListID);
			Mech::GameModel *mech_model = Cast_Pointer(Mech::GameModel *, model_resource.GetPointer());

			//add to the running total
			totalMechValues += (MoneyType)mech_model->tradeValue;

		}

		//Entity::GetGameModelResourceFromDataListID(&model_resource, mech_plug->GetMechResourceID());
		//Mech::GameModel *mech_model = Cast_Pointer(Mech::GameModel *, model_resource.GetPointer());
		//Resource mech_instance_resource(mech_plug->GetMechResourceID());
		//Mech::GameModel *mech_model = Cast_Pointer(Mech::GameModel *, mech_instance_resource.GetPointer());

	}

	return (int)((float)totalMechValues * CORPORATION_CYCLE_EXPENSE_FRACTION);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

//takes a type of graph and returns all the data for it
void MWCorporation::GetGraphData (char type, int **data, int &size)
{
	size = MWCorporation::m_iDate;
//	if (MWCorporation::m_iDate)
//		*data = new int[MWCorporation::m_iDate]; //GosMalloc/GosFree
//	else
//		return;

	int i;

	switch (type)
	{
	case InfamyTAG:
		for (i=0; i>MWCorporation::m_iDate; i++) 
		{
			(*data)[i] = MWCorporation::m_infamy[i];
		}
		break;
	case UnitStrenthTAG:
		for (i=0; i>MWCorporation::m_iDate; i++) 
		{
			(*data)[i] = MWCorporation::m_unitStrength[i];
		}
		break;
	case SteinerTAG:
		for (i=0; i>MWCorporation::m_iDate; i++) 
		{
			(*data)[i] = MWCorporation::m_steinerFactionRating[i];
		}
		break;
	case DavionTAG:
		for (i=0; i>MWCorporation::m_iDate; i++) 
		{
			(*data)[i] = MWCorporation::m_davionFactionRating[i];
		}
		break;
	case NobilityTAG:
		for (i=0; i>MWCorporation::m_iDate; i++) 
		{
			(*data)[i] = MWCorporation::m_nobility[i];
		}
		break;

	default:
		return; //failed, invalid graph requested

	}

	return;
}


//++*++ Non-Trivial Update and Set Methods

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

//goes and gets the top 8 mechs and adds their dragoon values together
int MWCorporation::UpdateAndSetCurrentUnitStrength (void)
{
	if ((MWCorporation::dwFlags & MWCORPORATION_UNIT_STRENGTH_VALID) == MWCORPORATION_UNIT_STRENGTH_VALID)
		return 0; //FAILURE -- already set

	int topValues[NUM_OF_DRAGOONS_FOR_UNIT_STRENGTH] = {0,0,0,0,0,0,0,0}; //8
	int smallest = 0;
	int smallestIndex = 0;
	int i;
	int sumTotal;

	//I need the m_mechTable from MWGame -- NOT MWApplication
	Check_Object(MWGame::GetInstance());

	Stuff::SortedChainIteratorOf<MechTablePlug *, Stuff::MString> mech_iterator (&MWGame::GetInstance()->m_mechTable);

	MechTablePlug *mech_plug;
	Resource model_resource;
	//Mech::CreateMessage *mech_create_message;
	//cycle through the mech table of company owned mechs
	while((mech_plug = mech_iterator.ReadAndNext()) != NULL)
	{

		if ((MWApplication::GetInstance()) && (MWGame::GetInstance()))
		{
			Check_Object(mech_plug);

			Stuff::MString basic_name = mech_plug->GetOriginalName(); //with all numbers stripped from the original name
			//strip the numbers
			for (i=0; i<basic_name.GetLength(); i++)
			{
				if (basic_name[i] < 'A')
				{
					basic_name[i] = '\0';
					break;
				}
			}

			//Find the mech from the MWGame's mechTable in the MWApplication's mechTable to get its tradeValue
			MWTableEntry *mech_entry = MWApplication::GetInstance()->m_mechTable->FindEntry(basic_name);
			Check_Object(mech_entry);

			Resource mech_resource(mech_entry->GetEntryResourceID());
			Verify(mech_resource.DoesResourceExist());

			Mech::CreateMessage *mech_create_message;
			mech_create_message = Cast_Pointer(Mech::CreateMessage *, mech_resource.GetPointer());
			Resource model_resource;
			Entity::GetGameModelResourceFromDataListID(&model_resource, mech_create_message->dataListID);
			Mech::GameModel *mech_model = Cast_Pointer(Mech::GameModel *, model_resource.GetPointer());

			//find the smallest top_value
			smallestIndex = 0;
			smallest = topValues[smallestIndex];
			for (i=1; i<NUM_OF_DRAGOONS_FOR_UNIT_STRENGTH; i++)
			{
				if (topValues[i] < smallest)
				{
					smallest = topValues[i];
					smallestIndex = i;
				}
			}
			//compare the smallest top value to the dragoon value being reviewed
			if (mech_model->dragoonValue > topValues[smallestIndex])
			{
				topValues[smallestIndex] = mech_model->dragoonValue;
			}
		}
	}


	//add the top values
	sumTotal = 0;
	for (i=0; i<NUM_OF_DRAGOONS_FOR_UNIT_STRENGTH; i++)
	{
		sumTotal += topValues[i];
	}


	//Now cycle through all the weapons and add up their Battle Values
	//apparently... the subsystems (weapons) list is included as part of the salvage system....
	Check_Object (MWGame::GetInstance()->m_salvageManager);

	Stuff::SortedChainIteratorOf<SalvagePlug*, int> weapon_iterator(&MWGame::GetInstance()->m_salvageManager->m_salvageList);	

	SalvagePlug *plug;
	while((plug = weapon_iterator.ReadAndNext()) != NULL)
	{
		//Check_Object(plug->m_subsystem);
		if (plug->m_subsystem)
		{
			if(plug->m_subsystem->IsDerivedFrom(Weapon::DefaultData))
			{
				sumTotal += plug->m_subsystem->GetGameModel()->battleValue;
			}
		}
	}

	m_unitStrength.push_back(sumTotal);

	MWCorporation::dwFlags |= MWCORPORATION_UNIT_STRENGTH_VALID;


	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::SetCurrentInfamy (int value)  
{
	
	if ((MWCorporation::dwFlags & MWCORPORATION_INFAMY_VALID) == MWCORPORATION_INFAMY_VALID)
		return 0; //FAILURE -- already set
	std::vector<int> a;


	MWCorporation::m_infamy.push_back(value); 

	MWCorporation::dwFlags |= MWCORPORATION_INFAMY_VALID;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::SetCurrentSteinerFactionRating (int value)  
{ 
	if ((MWCorporation::dwFlags & MWCORPORATION_STEINER_RATING_VALID) == MWCORPORATION_STEINER_RATING_VALID)
		return 0; //FAILURE -- already set

	MWCorporation::m_steinerFactionRating.push_back(value); 

	MWCorporation::dwFlags |= MWCORPORATION_STEINER_RATING_VALID;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::SetCurrentDavionFactionRating (int value)  
{ 
	if ((MWCorporation::dwFlags & MWCORPORATION_DAVION_RATING_VALID) == MWCORPORATION_DAVION_RATING_VALID)
		return 0; //FAILURE -- already set

	MWCorporation::m_davionFactionRating.push_back(value); 

	MWCorporation::dwFlags |= MWCORPORATION_DAVION_RATING_VALID;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MWCorporation::SetCurrentNobility (int value) {
	if ((MWCorporation::dwFlags & MWCORPORATION_NOBILITY_VALID) == MWCORPORATION_NOBILITY_VALID)
		return 0; //FAILURE -- already set

	MWCorporation::m_nobility.push_back(value); 

	MWCorporation::dwFlags |= MWCORPORATION_NOBILITY_VALID;

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWCorporation::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}
