//Implementation of the market place interface 
#include "MW4Headers.hpp"
#include "MarketPlace.hpp"

#include <gosScript\gosScriptHeaders.hpp>

#include "Mech.hpp"
#include "Subsystem.hpp"
#include "Weapon.hpp"
#include "SubsystemClassData.hpp"
#include "MWTable.hpp"
#include "MWApplication.hpp"
#include "Salvage.hpp"
#include "MWGame.hpp"
#include "BlackMarket.hpp"
#if defined( BLACK_KNIGHT )
#include "mechlabheaders_BK.h"
#elif defined( MERCENARIES )
#include "mechlabheaders_MERCS.h"
#elif defined( VENGEANCE )
#include "mechlabheaders_VENG.h"
#endif
#include "..\buildnum\buildnum.h"

// This is the amount by which trade values are multiplied when offered by the black market
#define BLACKMARKET_MARKUP	1.10f

/////////////////////////////////
//The Black Market Chits ///////
//BlackMarketChit::BlackMarketChit (int chitTypeID, char* chitName, MoneyType tradeValue): //**- 
BlackMarketChit::BlackMarketChit (int chitTypeID, char* chitName, float tradeValue):
	Plug(Plug::DefaultData),
	m_chitName (chitName),
	m_chitTypeID (chitTypeID),
	m_count (1),
	m_tradeValue (tradeValue)

{
	// Look up range, damage, heat, recycle values if this is a weapon; set them all to
	// 0 if it's a Mech (since they're not used in that case)
	if (chitTypeID < FirstMechChitID)
	{
#if defined( VENGEANCE ) || defined( BLACK_KNIGHT )
		MWMechPakTableEntry* weaponEntry = MWApplication::GetInstance()->m_weaponsTable->FindEntry(chitName);
#else
		MWTableEntry* weaponEntry = MWApplication::GetInstance()->m_weaponsTable->FindEntry(chitName);
#endif
		Check_Object (weaponEntry);
		Resource modelResource;
		Entity::GetGameModelResourceFromDataListID (&modelResource, weaponEntry->GetEntryResourceID());
		Verify (modelResource.DoesResourceExist());

		const Weapon::GameModel *weaponModel =
			Cast_Pointer (Weapon::GameModel*, modelResource.GetPointer ());
		Check_Pointer (weaponModel);
			
		m_range = weaponModel->maxDistance;
		m_damage = weaponModel->damageAmount * weaponModel->numFire;
		if(weaponModel->itemID == W_ArtilleryStrike)
			m_damage = 40.0f;
		m_heat = weaponModel->heat * 2.0f;
		m_recycle = weaponModel->reloadTime;
	}
	//It's a Mech
	else
	{
		m_range = 0.0f;
		m_damage = 0.0f;
		m_heat = 0.0f;
		m_recycle = 0.0f;
	}
}


BlackMarketChit::BlackMarketChit (int chitTypeID, char* chitName):
	Plug(Plug::DefaultData),
	m_chitName (chitName),
	m_chitTypeID (chitTypeID),
	m_count (1)
{				
	//need to look up the trade value and weapon parameters


	//if it is a weapon
	if (chitTypeID < FirstMechChitID)
	{
#if defined( VENGEANCE ) || defined( BLACK_KNIGHT )
		MWMechPakTableEntry* weaponEntry = MWApplication::GetInstance()->m_weaponsTable->FindEntry(chitName);
#else
		MWTableEntry* weaponEntry = MWApplication::GetInstance()->m_weaponsTable->FindEntry(chitName);
#endif
		Check_Object (weaponEntry);
		Resource modelResource;
		Entity::GetGameModelResourceFromDataListID (&modelResource, weaponEntry->GetEntryResourceID());
		Verify (modelResource.DoesResourceExist());

		const Weapon::GameModel *weaponModel =
			Cast_Pointer (Weapon::GameModel*, modelResource.GetPointer ());
		Check_Pointer (weaponModel);
			
		m_tradeValue = weaponModel->tradeValue;

		m_range = weaponModel->maxDistance;
		m_damage = weaponModel->damageAmount * weaponModel->numFire;
		if(weaponModel->itemID == W_ArtilleryStrike)
			m_damage = 40.0f;
		m_heat = weaponModel->heat * 2.0f;
		m_recycle = weaponModel->reloadTime;
	}
	//It's a Mech
	else
	{
#if defined( VENGEANCE ) || defined( BLACK_KNIGHT )
		MWMechPakTableEntry* mechEntry = MWApplication::GetInstance()->m_mechChassisTable->FindEntry(chitName);
#else
		MWTableEntry* mechEntry = MWApplication::GetInstance()->m_mechChassisTable->FindEntry(chitName);
#endif
		Check_Object (mechEntry);
		Resource modelResource;
		Entity::GetGameModelResourceFromDataListID (&modelResource, mechEntry->GetEntryResourceID());
		Verify (modelResource.DoesResourceExist());

		const Mech::GameModel *mechModel =
			Cast_Pointer (Mech::GameModel*, modelResource.GetPointer());
		Check_Object (mechModel);

		m_tradeValue = mechModel->tradeValue;

		m_range = 0.0f;
		m_damage = 0.0f;
		m_heat = 0.0f;
		m_recycle = 0.0f;
	}
}

///////////////////////////////////////////////////////////////////////

MarketPlace* MarketPlace::Instance = NULL;

MarketPlace::MarketPlace():
	m_salvageChits   (NULL, true),
	m_offeringChits  (NULL, true),
	m_marketChits    (NULL, true),
	m_acquiringChits (NULL, true)
{


}

MarketPlace::~MarketPlace()
{
	ShutDown();
}


void MarketPlace::StartUp()
{
	InitializeChits ();

	gosScript_RegisterCallback("BM_CallbackHandler",&BM_CallbackHandler,GOSVAR_INT,0,NULL);
}


void MarketPlace::ShutDown()
{
	gosScript_UnregisterCallback ("BM_CallbackHandler");

}

int MarketPlace::Exit()
{
	MWGame::GetInstance()->ResetBlackMarketManager();
	return 1;
}

///////////////  GOS script call backs  ////////////////////////////

int MarketPlace::BM_CallbackHandler(void* instance, int count, void* data[])
{
	Check_Pointer (MarketPlace::Instance);

	switch (CALLBACKID)
	{

		case BMDataSetupSalvageChits:
			return MarketPlace::Instance->SetupSalvageChits(data, count);
		case BMDataSetupOfferingChits:
			return MarketPlace::Instance->SetupOfferingChits(data, count);
		case BMDataSetupMarketChits:
			return MarketPlace::Instance->SetupMarketChits (data, count);
		case BMDataSetupAcquiringChits:
			return MarketPlace::Instance->SetupAcquiringChits (data, count);

		case BMDataSetupBeamWeaponSalvageChits:
			return MarketPlace::Instance->SetupBeamWeaponSalvageChits (data, count);
		case BMDataSetupBallisticWeaponSalvageChits:
			return MarketPlace::Instance->SetupBallisticWeaponSalvageChits (data, count);
		case BMDataSetupMissileWeaponSalvageChits:
			return MarketPlace::Instance->SetupMissileWeaponSalvageChits (data, count);
		case BMDataSetupMechSalvageChits:
			return MarketPlace::Instance->SetupMechSalvageChits (data, count);

		case BMDataSetupBeamWeaponMarketChits:
			return MarketPlace::Instance->SetupBeamWeaponMarketChits (data, count);
		case BMDataSetupBallisticWeaponMarketChits:
			return MarketPlace::Instance->SetupBallisticWeaponMarketChits (data, count);
		case BMDataSetupMissileWeaponMarketChits:
			return MarketPlace::Instance->SetupMissileWeaponMarketChits (data, count);
		case BMDataSetupMechMarketChits:
			return MarketPlace::Instance->SetupMechMarketChits (data, count);

		case BMOfferItemForTrade :
			return MarketPlace::Instance->OfferItemForTrade(data,count);
		case BMCancelOfferForTrade:
			return MarketPlace::Instance->CancelOfferForTrade (data,count);
		case BMAcquireItemForTrade:
			return MarketPlace::Instance->AcquireItemForTrade (data, count);
		case BMCancelAcquireForTrade:
			return MarketPlace::Instance->CancelAcquireForTrade (data, count);
		case BMGetOfferingValue:
			return MarketPlace::Instance->GetOfferingValue (data,count);
		case BMGetAcquiringValue:
			return MarketPlace::Instance->GetAcquiringValue (data,count);
		case BMExecuteTrade:
			return MarketPlace::Instance->ExecuteTrade (data,count);
		case BMIsTradeValid:
			return MarketPlace::Instance->IsTradeValid (data,count);

		case BMRestore:
			return MarketPlace::Instance->CancelAllTrades (data,count);
		case BMExit:
			return MarketPlace::Instance->Exit();
	}

	return 1;
}






int MarketPlace::SetupSalvageChits (void* data[], int count)
{
	return SetupChits (m_salvageChits, false, data, count);
}

int MarketPlace::SetupOfferingChits (void* data[], int count)
{
	return SetupChits (m_offeringChits, false, data, count);
}

int MarketPlace::SetupMarketChits (void* data[], int count)
{
	return SetupChits (m_marketChits, true, data, count);
}

int MarketPlace::SetupAcquiringChits (void* data[], int count)
{
	return SetupChits (m_acquiringChits, true, data, count);

}

int MarketPlace::SetupBeamWeaponSalvageChits (void* data[], int count)
{
	return SetupBeamWeaponChits(m_salvageChits, false, data, count);
}

int MarketPlace::SetupBallisticWeaponSalvageChits (void* data[], int count)
{
	return SetupBallisticWeaponChits(m_salvageChits, false, data, count);
}

int MarketPlace::SetupMissileWeaponSalvageChits (void* data[], int count)
{
	return SetupMissileWeaponChits(m_salvageChits, false, data, count);
}

int MarketPlace::SetupMechSalvageChits (void* data[], int count)
{
	return SetupMechChits(m_salvageChits, false, data, count);
}

int MarketPlace::SetupBeamWeaponMarketChits (void* data[], int count)
{
	return SetupBeamWeaponChits(m_marketChits, true, data, count);
}

int MarketPlace::SetupBallisticWeaponMarketChits (void* data[], int count)
{
	return SetupBallisticWeaponChits(m_marketChits, true, data, count);
}

int MarketPlace::SetupMissileWeaponMarketChits (void* data[], int count)
{
	return SetupMissileWeaponChits(m_marketChits, true, data, count);
}

int MarketPlace::SetupMechMarketChits (void* data[], int count)
{
	return SetupMechChits(m_marketChits, true, data, count);
}

int MarketPlace::OfferItemForTrade (void* data[], int count)
{
	int* id = INTARRAYPARAM (1);
	int* isLastMech = INTARRAYPARAM (2);
	*isLastMech = OfferItemForTrade (*id);
	return 1;
}

int MarketPlace::CancelOfferForTrade (void* data[], int count)
{
	int* id = INTARRAYPARAM (1);
	CancelOfferForTrade (*id);
	return 1;
}

int MarketPlace::AcquireItemForTrade (void* data[], int count)
{
	int* id  = INTARRAYPARAM (1);
	AcquireItemForTrade (*id);
	return 1;
}

int MarketPlace::CancelAcquireForTrade (void* data[], int count)
{
	int* id = INTARRAYPARAM (1);
	CancelAcquireForTrade (*id);
	return 1;
}

int MarketPlace::CancelAllTrades (void* data[], int count)
{
	// Remove all chits from offering list and put them back in salvage list
	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_offeringChits);
	BlackMarketChit* thisChit;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		int count = thisChit->GetCount();
		for (int i = 0; i < count; i++)
			CancelOfferForTrade(thisChit->GetChitTypeID());
	}

	// Remove all chits from acquiring list and put them back in market list
	SortedChainIteratorOf <BlackMarketChit*, int> iterator2 (&m_acquiringChits);
	while ((thisChit = iterator2.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		int count = thisChit->GetCount();
		for (int i = 0; i < count; i++)
			CancelAcquireForTrade(thisChit->GetChitTypeID());
	}

	return 1;
}

int MarketPlace::ExecuteTrade (void *data[], int count)
{
	if ( ExecuteTrade())
	{
		return 1;
	}
	else
	{
		return 0;
	}

}

int MarketPlace::IsTradeValid (void* data[], int count)
{
	if (IsTradeValid())
	{
		return 1;
	}
	else
	{
		return 0;
	}

}

//
//    THE FLOAT TO INT CONVERSION FOR THE MONEY SYSTEM
//
// NOTE: *BLACK_KNIGHT uses floats for its money system in most places
//         this is also occasionally manifested as a typedefed Stuff:Scalar (which is also a float)
//         here it casts it to an int.
//       *MERCENARIES requires integers because ammounts will often be in the millions or billions
//       
//       To handle this, a new type "MoneyType" has been created in Adept.hpp.  It is defined as floats in
//       BK and ints in MERCS...
//
//       In some cases MoneyType does not work, like where Stuff::Scalar is used, or where hard coded values
//       like 0.0f are used.  In these cases IFDEF blocks are used instead.
//
// POSTPONED UNTIL MARKET SYSTEM UPDATES -- find all changes with a search for "//**- "
//
//


int MarketPlace::GetOfferingValue  (void *data[], int count)
{
	return (int)GetTotalOfferingValue();

}

int MarketPlace::GetAcquiringValue (void * data[], int count)
{
	return (int) GetTotalAcquiringValue();

}



void MarketPlace::InitializeChits ()
{
	m_salvageChits.DeletePlugs();
	m_offeringChits.DeletePlugs();
	m_marketChits.DeletePlugs();
	m_acquiringChits.DeletePlugs();

	InitializeSalvageChits();
	InitializeBlackMarketChits();
}


//Go through the salvage manager and the Mecch 
//table and create the chits for those Items 
//in order to trade on the Black Market 
void MarketPlace::InitializeSalvageChits()
{
	//Do the Weapons first, them the Mechs
	
	Check_Object (MWGame::GetInstance());
	Check_Object (MWGame::GetInstance()->m_salvageManager);

	SortedChainIteratorOf <SalvagePlug*, int> subsysIterator (&MWGame::GetInstance()->m_salvageManager->m_salvageList);
	SalvagePlug *salvagePlug;
	while ((salvagePlug = subsysIterator.ReadAndNext()) != NULL)
	{
		Check_Object (salvagePlug);
		Resource modelResource (salvagePlug->m_salvageID);
		Verify (modelResource.DoesResourceExist());

		Subsystem::GameModel* subModel =Cast_Pointer (
			Subsystem::GameModel*, modelResource.GetPointer ());

		if ((subModel->itemID >= FirstWeaponID) &&
			(subModel->itemID <= LastWeaponID))
		{
			//it is a weapon
			for (int i =0; ( i <salvagePlug->m_count); i++)
			{
				AddSalvageChit (subModel->itemID, MWApplication::GetInstance()->GetWeaponName (subModel->itemID));		
			}
		}
	}
//now we need to get the Mechs
	SortedChainIteratorOf <MechTablePlug*, MString> mechIterator (&MWGame::GetInstance()->m_mechTable);
	MechTablePlug *mechPlug;

	while ((mechPlug = mechIterator.ReadAndNext()) != NULL)
	{
		if ((mechPlug->GetStatus() != MechTablePlug::DestroyedStatus) && (mechPlug->GetStatus() != MechTablePlug::DamagedStatus) && (mechPlug->GetStatus() != MechTablePlug::CrippledStatus))
		{
			AddSalvageChit (mechPlug->GetMechID()+ FirstMechChitID, MWApplication::GetInstance()->GetMechName(mechPlug->GetMechID()));
		}
	}
}

void MarketPlace::InitializeBlackMarketChits()
{
	Check_Object (MWGame::GetInstance ());
	Check_Object (MWGame::GetInstance ()->m_blackMarketManager);

	SortedChainIteratorOf <BlackMarketPlug*, int> iterator (&MWGame::GetInstance()->m_blackMarketManager->m_chitList);
	BlackMarketPlug* marketPlug;

	while ((marketPlug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (marketPlug);
		for ( int i =0; (i < marketPlug->GetCount()); i++)
		{
			AddMarketChit (marketPlug->GetChitTypeID(), marketPlug->GetChitName());
		}
	}
}
///////////////////////////////////////////////////////////

int MarketPlace::SetupChits (Stuff::SortedChainOf<BlackMarketChit*, int>& chitList, bool applyMarkup, void* data[], int count)
{
	int* idArray = INTARRAYPARAM (1);
//#if defined( BLACK_KNIGHT ) //**- 
	Scalar* tradeValueArray = SCALARARRAYPARAM (2);
//#elif defined( MERCENARIES )
//	MoneyType* tradeValueArray = MONEYTYPEARRAYPARAM (2);
//#endif // BK else MERCS
	Scalar *damage_array = SCALARARRAYPARAM(3);
	Scalar *range_array = SCALARARRAYPARAM(4);
	Scalar *heat_array = SCALARARRAYPARAM(5);
	Scalar *recycle_array = SCALARARRAYPARAM(6);
	int* inventoryCountArray = INTARRAYPARAM (7);
	int* numTypes =  INTARRAYPARAM (8);


	

	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&chitList);
	BlackMarketChit* thisChit;
	int itemTypes = 0;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		idArray[itemTypes] = thisChit->GetChitTypeID();
		tradeValueArray [itemTypes]  = thisChit ->GetTradeValue();
		if (applyMarkup)
//			tradeValueArray [itemTypes] = (MoneyType)(tradeValueArray [itemTypes] * BLACKMARKET_MARKUP); //**- 
			tradeValueArray [itemTypes] *= BLACKMARKET_MARKUP;
		inventoryCountArray [itemTypes] = thisChit ->GetCount();
		damage_array [itemTypes] = thisChit->GetDamage();
		range_array [itemTypes] = thisChit->GetRange();
		heat_array [itemTypes] = thisChit->GetHeat();
		recycle_array [itemTypes] = thisChit->GetRecycle();
		itemTypes ++;
	}

	*numTypes = itemTypes;
	return 1;
}

int MarketPlace::SetupBeamWeaponChits (Stuff::SortedChainOf<BlackMarketChit*, int>& chitList, bool applyMarkup, void* data[], int count)
{
	int* idArray = INTARRAYPARAM (1);
//#if defined( BLACK_KNIGHT ) //**- 
	Scalar* tradeValueArray = SCALARARRAYPARAM (2);
//#elif defined( MERCENARIES )
//	MoneyType* tradeValueArray = MONEYTYPEARRAYPARAM (2);
//#endif // BK else MERCS
	Scalar *damage_array = SCALARARRAYPARAM(3);
	Scalar *range_array = SCALARARRAYPARAM(4);
	Scalar *heat_array = SCALARARRAYPARAM(5);
	Scalar *recycle_array = SCALARARRAYPARAM(6);
	int* inventoryCountArray = INTARRAYPARAM (7);
	int* numTypes =  INTARRAYPARAM (8);

	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&chitList);
	BlackMarketChit* thisChit;
	int itemTypes = 0;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);

		// Only process if this is a beam weapon
		int chitTypeID = thisChit->GetChitTypeID();
		if ((chitTypeID >= FirstBeamID) && (chitTypeID <= LastBeamID))
		{
			idArray[itemTypes] = thisChit->GetChitTypeID();
			tradeValueArray [itemTypes]  = thisChit ->GetTradeValue();
			if (applyMarkup)
//				tradeValueArray [itemTypes] = (MoneyType)(tradeValueArray [itemTypes] * BLACKMARKET_MARKUP); //**- 
				tradeValueArray [itemTypes] *= BLACKMARKET_MARKUP;
			inventoryCountArray [itemTypes] = thisChit ->GetCount();
			damage_array [itemTypes] = thisChit->GetDamage();
			range_array [itemTypes] = thisChit->GetRange();
			heat_array [itemTypes] = thisChit->GetHeat();
			recycle_array [itemTypes] = thisChit->GetRecycle();
			itemTypes ++;
		}
	}

	*numTypes = itemTypes;
	return 1;
}

int MarketPlace::SetupBallisticWeaponChits (Stuff::SortedChainOf<BlackMarketChit*, int>& chitList, bool applyMarkup, void* data[], int count)
{
	int* idArray = INTARRAYPARAM (1);
//#if defined( BLACK_KNIGHT ) //**- 
	Scalar* tradeValueArray = SCALARARRAYPARAM (2);
//#elif defined( MERCENARIES )
//	MoneyType* tradeValueArray = MONEYTYPEARRAYPARAM (2);
//#endif // BK else MERCS
	Scalar *damage_array = SCALARARRAYPARAM(3);
	Scalar *range_array = SCALARARRAYPARAM(4);
	Scalar *heat_array = SCALARARRAYPARAM(5);
	Scalar *recycle_array = SCALARARRAYPARAM(6);
	int* inventoryCountArray = INTARRAYPARAM (7);
	int* numTypes =  INTARRAYPARAM (8);

	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&chitList);
	BlackMarketChit* thisChit;
	int itemTypes = 0;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);

		// Only process if this is a ballistic weapon
		int chitTypeID = thisChit->GetChitTypeID();
		if ((chitTypeID >= FirstProjectileID) && (chitTypeID <= LastProjectileID))
		{
			idArray[itemTypes] = thisChit->GetChitTypeID();
			tradeValueArray [itemTypes]  = thisChit ->GetTradeValue();
			if (applyMarkup)
//				tradeValueArray [itemTypes] = (MoneyType)(tradeValueArray [itemTypes] * BLACKMARKET_MARKUP); //**- 
				tradeValueArray [itemTypes] *= BLACKMARKET_MARKUP;
			inventoryCountArray [itemTypes] = thisChit ->GetCount();
			damage_array [itemTypes] = thisChit->GetDamage();
			range_array [itemTypes] = thisChit->GetRange();
			heat_array [itemTypes] = thisChit->GetHeat();
			recycle_array [itemTypes] = thisChit->GetRecycle();
			itemTypes ++;
		}
	}

	*numTypes = itemTypes;
	return 1;
}

int MarketPlace::SetupMissileWeaponChits (Stuff::SortedChainOf<BlackMarketChit*, int>& chitList, bool applyMarkup, void* data[], int count)
{
	int* idArray = INTARRAYPARAM (1);
//#if defined( BLACK_KNIGHT ) //**- 
	Scalar* tradeValueArray = SCALARARRAYPARAM (2);
//#elif defined( MERCENARIES )
//	MoneyType* tradeValueArray = MONEYTYPEARRAYPARAM (2);
//#endif // BK else MERCS
	Scalar *damage_array = SCALARARRAYPARAM(3);
	Scalar *range_array = SCALARARRAYPARAM(4);
	Scalar *heat_array = SCALARARRAYPARAM(5);
	Scalar *recycle_array = SCALARARRAYPARAM(6);
	int* inventoryCountArray = INTARRAYPARAM (7);
	int* numTypes =  INTARRAYPARAM (8);

	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&chitList);
	BlackMarketChit* thisChit;
	int itemTypes = 0;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);

		// Only process if this is a missile weapon
		int chitTypeID = thisChit->GetChitTypeID();
		if ((chitTypeID >= FirstMissileID) && (chitTypeID <= LastMissileID))
		{
			idArray[itemTypes] = thisChit->GetChitTypeID();
			tradeValueArray [itemTypes]  = thisChit ->GetTradeValue();
			if (applyMarkup)
//				tradeValueArray [itemTypes] = (MoneyType)(tradeValueArray [itemTypes] * BLACKMARKET_MARKUP); //**- 
				tradeValueArray [itemTypes] *= BLACKMARKET_MARKUP;
			inventoryCountArray [itemTypes] = thisChit ->GetCount();
			damage_array [itemTypes] = thisChit->GetDamage();
			range_array [itemTypes] = thisChit->GetRange();
			heat_array [itemTypes] = thisChit->GetHeat();
			recycle_array [itemTypes] = thisChit->GetRecycle();
			itemTypes ++;
		}
	}

	*numTypes = itemTypes;
	return 1;
}

int MarketPlace::SetupMechChits (Stuff::SortedChainOf<BlackMarketChit*, int>& chitList, bool applyMarkup, void* data[], int count)
{
	int* idArray = INTARRAYPARAM (1);
//#if defined( BLACK_KNIGHT ) //**- 
	Scalar* tradeValueArray = SCALARARRAYPARAM (2);
//#elif defined( MERCENARIES )
//	MoneyType* tradeValueArray = MONEYTYPEARRAYPARAM (2);
//#endif // BK else MERCS
	Scalar *damage_array = SCALARARRAYPARAM(3);
	Scalar *range_array = SCALARARRAYPARAM(4);
	Scalar *heat_array = SCALARARRAYPARAM(5);
	Scalar *recycle_array = SCALARARRAYPARAM(6);
	int* inventoryCountArray = INTARRAYPARAM (7);
	int* numTypes =  INTARRAYPARAM (8);

	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&chitList);
	BlackMarketChit* thisChit;
	int itemTypes = 0;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);

		// Only process if this is a mech
		if (thisChit->GetChitTypeID() >= FirstMechChitID)
		{
			idArray[itemTypes] = thisChit->GetChitTypeID();
			tradeValueArray [itemTypes]  = thisChit ->GetTradeValue();
			if (applyMarkup)
//				tradeValueArray [itemTypes] = (MoneyType)(tradeValueArray [itemTypes] * BLACKMARKET_MARKUP); //**- 
				tradeValueArray [itemTypes] *= BLACKMARKET_MARKUP;
			inventoryCountArray [itemTypes] = thisChit ->GetCount();
			damage_array [itemTypes] = thisChit->GetDamage();
			range_array [itemTypes] = thisChit->GetRange();
			heat_array [itemTypes] = thisChit->GetHeat();
			recycle_array [itemTypes] = thisChit->GetRecycle();
			itemTypes ++;
		}
	}

	*numTypes = itemTypes;
	return 1;
}


////////////////////////////////////////////////////////////////////
//MoneyType MarketPlace::GetTotalOfferingValue () //**- 
float MarketPlace::GetTotalOfferingValue () 
{
//#if defined( BLACK_KNIGHT ) //**- 
//	MoneyType totalValue = 0.0f; //floatToInt conversion of Money handling between BK and MERCS -- see MW4.hpp
	float totalValue = 0.0f;
//#elif defined( MERCENARIES )
//	MoneyType totalValue = 0;
//#endif // BK else MERCS
	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_offeringChits);
	BlackMarketChit* thisChit;

	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		totalValue += (int)( thisChit->GetTradeValue() * thisChit->GetCount());
	}
	return totalValue;
}

//MoneyType MarketPlace::GetTotalAcquiringValue () //**- 
float MarketPlace::GetTotalAcquiringValue ()
{
//#if defined( BLACK_KNIGHT ) //**- 
//	MoneyType totalValue = 0.0f;
	float totalValue = 0.0f;
//#elif defined( MERCENARIES )
//	MoneyType totalValue = 0;
//#endif // BK else MERCS
	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_acquiringChits);
	BlackMarketChit* thisChit;

	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		totalValue += ((int)(thisChit ->GetTradeValue() * BLACKMARKET_MARKUP) * thisChit->GetCount ());
	}

	return totalValue;
}


bool MarketPlace::ExecuteTrade()
{
	bool tradeExecuted = false;
	if (IsTradeValid())
	{
		MakePayment ();
		ReceiveGoods();
		
		//now save out the game
		MWGame::GetInstance()->SaveMWGame(MWGame::GetInstance()->GetGameName(), false);

		//now reset the chit lists 
		InitializeChits();
		tradeExecuted = true;
	}

	return tradeExecuted;
}

bool MarketPlace::IsTradeValid()
{
	return ((((int)GetTotalAcquiringValue ()) <= ((int)GetTotalOfferingValue ()))&&(GetTotalAcquiringValue () > 0));
}

void MarketPlace::MakePayment()
{
	//move the offering stuff first
	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_offeringChits);
	BlackMarketChit* thisChit;
	while ((thisChit=iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		for ( int i =0; (i< thisChit->GetCount()); i++)
		{
			
			//remove the items from the salvage 
			if (thisChit->GetChitTypeID () < FirstMechChitID)
					//it is a weapon
			{
				MWGame::GetInstance()->m_salvageManager->RemoveSalvage(thisChit->GetChitTypeID());
			}
			else //it's a Mech remove one from the Mech Table
			{
				//first one must be found
				SortedChainIteratorOf <MechTablePlug*, MString> mechIterator (&MWGame::GetInstance()->m_mechTable);
				MechTablePlug* mechToBeRemoved =NULL;
				MechTablePlug* mechPlug;
				while ((mechPlug = mechIterator.ReadAndNext()) != NULL)
				{
					if (mechPlug->GetStatus() != MechTablePlug::DestroyedStatus)
					{
						if (mechPlug->GetMechID() == (thisChit->GetChitTypeID() - FirstMechChitID))
						{
							mechToBeRemoved = mechPlug;
							break;
						}
					}
				}					
				if (mechToBeRemoved != NULL)
				{
					//if the 'Mech has weapons they need to be removed and added to salvage
					Resource mech_resource (mechToBeRemoved->GetMechResourceID());
					Verify (mech_resource.DoesResourceExist());
					ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
					Entity *entity = Entity::CreateEntity (&mech_resource, &base_id);
					Verify(entity->IsDerivedFrom(Mech::DefaultData));
					Mech* newMech = Cast_Object(Mech *, entity);

					Check_Object(newMech);
					ChainIteratorOf<Subsystem *> iterator(&newMech->subsystemsInVehicle);	
					Subsystem *subsystem;

					while((subsystem = iterator.ReadAndNext()) != NULL)
					{
						Check_Object(subsystem);
						if(subsystem->IsDerivedFrom(Weapon::DefaultData))
						{
							MWGame::GetInstance()->m_salvageManager->AddSalvage 
								(subsystem,MWApplication::GetInstance()->GetWeaponName (subsystem->subsystemIndex),false);
						}
					}

					MWGame::GetInstance()->m_mechTable.Remove(mechToBeRemoved);	
				}
			}
			//add item to the market
			MWGame::GetInstance()->m_blackMarketManager->AddItem (thisChit->GetChitTypeID(), thisChit->GetChitName());
		}
	}
}


void MarketPlace::ReceiveGoods ()
{
	SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_acquiringChits);
	BlackMarketChit* thisChit;
	while ((thisChit = iterator.ReadAndNext()) != NULL)
	{
		Check_Object (thisChit);
		for ( int i =0; (i< thisChit->GetCount()); i++)
		{
			//remove it from the market
			MWGame::GetInstance()->m_blackMarketManager->RemoveItem(thisChit->GetChitTypeID());
		
			if (thisChit->GetChitTypeID () < FirstMechChitID)
			{  //its a weapon

#if defined( BLACK_KNIGHT )
				MWGame::GetInstance()->m_salvageManager->GetAndAddWeaponSalvage (thisChit->GetChitName(),1);
#elif defined( MERCENARIES )
				MoneyType dummy;
				MWGame::GetInstance()->m_salvageManager->GetAndAddWeaponSalvage (thisChit->GetChitName(),1, dummy);
#endif
			}
			else
			{  //it mech 
#if defined( BLACK_KNIGHT )
				MWGame::GetInstance()->GetAndAddStrippedMechInstance (thisChit->GetChitName());
#elif defined( MERCENARIES )
				MoneyType dummy;
				MWGame::GetInstance()->GetAndAddStrippedMechInstance (thisChit->GetChitName(), dummy);
#endif
			}
		}
	}
}



/////////////////////////////////////////////////////////////////////////////////
//Members to manage the Chit list 
//Remember that the Mech IDs are offset by FirstMechChitID
//And the names are the ones in the Weapon's table, and the Mech chassis table
/////////////////////////////////////////////////////////////////////////////////
int  MarketPlace::OfferItemForTrade (int id)
{
	BlackMarketChit* thisPlug = m_salvageChits.Find (id);
	if (thisPlug != NULL)
	{
		// If this chit is for a mech, and there's only one mech in the salvage list,
		// then the user is trying to trade away their last mech.  If this is the case,
		// then the trade will not be completed and a 1 will be returned.  This value
		// will get passed back to the GOS script and tell it to display a dialog
		// indicating that the last mech cannot be traded.
		if (thisPlug->GetChitTypeID() >= FirstMechChitID)
		{
			// Count mechs in the salvage list
			int numMechs = 0;
			SortedChainIteratorOf <BlackMarketChit*, int> iterator (&m_salvageChits);
			BlackMarketChit* thisChit;
			while ((thisChit=iterator.ReadAndNext()) != NULL)
			{
				if (thisChit->GetChitTypeID() >= FirstMechChitID)
					numMechs++;
			}

			if (numMechs < 2)
				return 1;
		}

		AddOfferingChit (thisPlug->GetChitTypeID(), thisPlug->GetChitName(), thisPlug->GetTradeValue());
		RemoveSalvageChit (id);
	}

	// Return 0 to indicate that the offer was successful
	return 0;
}

void  MarketPlace::CancelOfferForTrade (int id)
{
	BlackMarketChit* thisPlug = m_offeringChits.Find (id);
	if (thisPlug != NULL)
	{
		AddSalvageChit (thisPlug->GetChitTypeID(), thisPlug->GetChitName(), thisPlug->GetTradeValue());
		RemoveOfferingChit (id);
	}
}

void  MarketPlace::AcquireItemForTrade (int id)
{
	BlackMarketChit* thisPlug = m_marketChits.Find (id);
	if (thisPlug != NULL)
	{
		AddAcquiringChit (thisPlug->GetChitTypeID(), thisPlug->GetChitName(), thisPlug->GetTradeValue());
		RemoveMarketChit (id);
	}

}

void  MarketPlace::CancelAcquireForTrade (int id)
{
	BlackMarketChit* thisPlug = m_acquiringChits.Find (id);
	if (thisPlug != NULL)
	{
		AddMarketChit (thisPlug->GetChitTypeID(), thisPlug ->GetChitName(), thisPlug->GetTradeValue());
		RemoveAcquiringChit(id);
	}
}


void MarketPlace::AddSalvageChit (int chitTypeID, char* chitName)
{
	BlackMarketChit* thisPlug = m_salvageChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		//need to make new Plug 
		thisPlug = new BlackMarketChit (chitTypeID, chitName);
		m_salvageChits.AddValue (thisPlug, chitTypeID);
	}
}

//void MarketPlace::AddSalvageChit (int chitTypeID, char* chitName, MoneyType tradeValue) //**- 
void MarketPlace::AddSalvageChit (int chitTypeID, char* chitName, float tradeValue)
{
	BlackMarketChit* thisPlug = m_salvageChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		//need to make new plug
		thisPlug = new BlackMarketChit (chitTypeID, chitName, tradeValue);
		m_salvageChits.AddValue (thisPlug, chitTypeID);
	}
}

void MarketPlace::RemoveSalvageChit (int chitTypeID)
{

	BlackMarketChit* thisPlug = m_salvageChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Subtract();
		if (thisPlug -> IsEmpty())
		{
			m_salvageChits.Remove (thisPlug);
			delete thisPlug;
		}
	}
}
///////////////////
void MarketPlace::AddOfferingChit (int chitTypeID, char* chitName)
{
	BlackMarketChit* thisPlug = m_offeringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		//need to make new plug
		thisPlug = new BlackMarketChit (chitTypeID, chitName);
		m_offeringChits .AddValue (thisPlug, chitTypeID);
	}
}

//void MarketPlace::AddOfferingChit (int chitTypeID, char* chitName, MoneyType tradeValue) //**- 
void MarketPlace::AddOfferingChit (int chitTypeID, char* chitName, float tradeValue)
{
	BlackMarketChit* thisPlug = m_offeringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		//need to make new plug
		thisPlug = new BlackMarketChit (chitTypeID, chitName, tradeValue);
		m_offeringChits.AddValue (thisPlug, chitTypeID);
	}

}

void MarketPlace::RemoveOfferingChit (int chitTypeID)
{
	BlackMarketChit* thisPlug = m_offeringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Subtract();
		if (thisPlug->IsEmpty())
		{
			m_offeringChits.Remove (thisPlug);
			delete thisPlug;
		}
	}
}
//////////////////////////////
void MarketPlace::AddMarketChit (int chitTypeID, char* chitName)
{
	BlackMarketChit* thisPlug = m_marketChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		//need to make a new plug 
		thisPlug = new BlackMarketChit (chitTypeID, chitName);
		m_marketChits.AddValue (thisPlug, chitTypeID);
	}
}

//void MarketPlace::AddMarketChit (int chitTypeID, char* chitName, MoneyType tradeValue) //**- 
void MarketPlace::AddMarketChit (int chitTypeID, char* chitName, float tradeValue)
{
	BlackMarketChit* thisPlug = m_marketChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{	
		//need to make new plug
		thisPlug = new BlackMarketChit (chitTypeID, chitName, tradeValue);
		m_marketChits.AddValue (thisPlug, chitTypeID);
	}
}


void MarketPlace::RemoveMarketChit(int chitTypeID)
{
	BlackMarketChit* thisPlug = m_marketChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Subtract();
		if (thisPlug->IsEmpty())
		{
			m_marketChits.Remove (thisPlug);
			delete thisPlug;
		}
	}
}
/////////////////////////
void MarketPlace::AddAcquiringChit (int chitTypeID, char* chitName)
{
	BlackMarketChit* thisPlug = m_acquiringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug ->Add();
	}
	else
	{
		//need to make new plug
		thisPlug = new BlackMarketChit (chitTypeID, chitName);
		m_acquiringChits.AddValue (thisPlug, chitTypeID);
	}

}

//void MarketPlace::AddAcquiringChit (int chitTypeID, char* chitName, MoneyType tradeValue) //**- 
void MarketPlace::AddAcquiringChit (int chitTypeID, char* chitName, float tradeValue)
{
	BlackMarketChit* thisPlug = m_acquiringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Add();
	}
	else
	{
		thisPlug = new BlackMarketChit (chitTypeID, chitName);
		m_acquiringChits.AddValue (thisPlug, chitTypeID);
	}
}

void MarketPlace::RemoveAcquiringChit (int chitTypeID)
{
	BlackMarketChit* thisPlug = m_acquiringChits.Find (chitTypeID);
	if (thisPlug != NULL)
	{
		thisPlug->Subtract();
		if (thisPlug->IsEmpty())
		{
			m_acquiringChits.Remove (thisPlug);
			delete thisPlug;
		}
	}
}

