// ======================================================================
//
// AuctionMarket.cpp (refactor of original Commodities Market code)
// copyright (c) 2004 Sony Online Entertainment
//
// Original Author: Matt Severenson
// Refactored by  : Doug Mellencamp
//
// ======================================================================

#include "FirstCommodityServer.h"
#include "CommodityServer.h"
#include "AuctionMarket.h"
#include "GameServerConnection.h"
#include "ConfigCommodityServer.h"
#include "DatabaseServerConnection.h"
#include "StringId.h"
#include "sharedFoundation/Crc.h"
#include "sharedLog/Log.h"
#include "serverNetworkMessages/AuctionBase.h"
#include "serverNetworkMessages/CMCreateAuctionMessage.h"
#include "serverNetworkMessages/CMCreateAuctionBidMessage.h"
#include "serverNetworkMessages/CMCreateLocationMessage.h"
#include "serverNetworkMessages/CMDeleteAuctionMessage.h"
#include "serverNetworkMessages/CMDeleteLocationMessage.h"
#include "serverNetworkMessages/CMUpdateAuctionMessage.h"
#include "serverNetworkMessages/CMUpdateLocationMessage.h"
#include "sharedNetworkMessages/DeleteCharacterMessage.h"
#include "serverNetworkMessages/LoadCommoditiesMessage.h"
#include "serverNetworkMessages/OnAcceptHighBidMessage.h"
#include "serverNetworkMessages/OnAddAuctionMessage.h"
#include "serverNetworkMessages/OnAddBidMessage.h"
#include "serverNetworkMessages/OnAuctionExpiredMessage.h"
#include "serverNetworkMessages/OnCancelAuctionMessage.h"
#include "serverNetworkMessages/OnCleanupInvalidItemRetrievalMessage.h"
#include "serverNetworkMessages/OnCreateVendorMarketMessage.h"
#include "serverNetworkMessages/OnGetItemDetailsMessage.h"
#include "serverNetworkMessages/OnGetItemMessage.h"
#include "serverNetworkMessages/OnGetPlayerVendorCountMessage.h"
#include "serverNetworkMessages/OnGetVendorOwnerMessage.h"
#include "serverNetworkMessages/OnGetVendorValueMessage.h"
#include "serverNetworkMessages/OnItemExpiredMessage.h"
#include "serverNetworkMessages/OnPermanentAuctionPurchasedMessage.h"
#include "serverNetworkMessages/OnQueryAuctionHeadersMessage.h"
#include "serverNetworkMessages/OnVendorRefuseItemMessage.h"
#include "serverNetworkMessages/OnUpdateVendorSearchOptionMessage.h"
#include "serverNetworkMessages/QueryVendorItemCountMessage.h"
#include "serverNetworkMessages/OnQueryVendorItemCountReplyMessage.h"
#include "serverNetworkMessages/UpdateVendorStatusMessage.h"
#include "serverNetworkMessages/VendorStatusChangeMessage.h"
#include "sharedFoundation/CalendarTime.h"
#include "sharedGame/CommoditiesAdvancedSearchAttribute.h"
#include "sharedGame/GameObjectTypes.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"

#include "utf8.h"
#include "UnicodeUtils.h"

namespace AuctionMarketNamespace
{
	std::string const  g_dummyName = "INVALID_CHARACTER";
	NetworkId const zeroNetworkId(static_cast<NetworkId::NetworkIdType>(0));
	NetworkId const negOneNetworkId(static_cast<NetworkId::NetworkIdType>(-1));
	char const * vendorStatus[] = {"Active", "Empty", "Unaccessed", "EmptyAndUnaccessed", "Endangered", "Removed"};

	// ======================================================================

	void encodeOOB(const Unicode::String & str, std::string & HexString )
	{
		char buffer [5];
		Unicode::String localCopy(str);
		Unicode::String::iterator z = localCopy.begin();
		while (z != localCopy.end())
		{
			if (sprintf (buffer, "%04X", *z) < 0)
			{
				WARNING(true, ("[Commodities Server ] : Writing converted OOB hex value to buffer failed in: TaskCreateAuction::encodeOOB.\n"));
			}
			else
			{
				HexString += buffer;
			}
			z++;
		}

		DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server ][HEX OOB IN] : %s \n", HexString.c_str()));

	}

	// ----------------------------------------------------------------------

	void GetHighBidInfo(
		Auction const * const auction,
		int & highBidOut,
		NetworkId & highBidderIdOut
	)
	{
		if (auction->IsImmediate())
		{
			highBidOut = auction->GetBuyNowPriceWithSalesTax();
			if (auction->GetHighBid())
			{
        		highBidderIdOut = auction->GetHighBid()->GetBidderId();
			}
		}
		else if (auction->GetHighBid())
		{
			highBidOut = auction->GetHighBid()->GetBid();
			highBidderIdOut = auction->GetHighBid()->GetBidderId();
		}
		else
		{
			highBidOut = auction->GetMinBid();
		}
	}

	// ----------------------------------------------------------------------

	AuctionDataHeader *MakeDataHeader(
		NetworkId const & playerId,
		Auction const * const auction,
		int const type,
		int const entranceCharge,
		AuctionBid const * const playerBid = nullptr
	)
	{
		AuctionDataHeader *header = new AuctionDataHeader;

		header->type = type;
		header->auctionId = auction->GetItem().GetItemId();
		header->itemId = auction->GetItem().GetItemId();
		header->itemNameLength = auction->GetItem().GetNameLength();
		header->itemName = auction->GetItem().GetName();
		header->minBid = auction->GetMinBid();
		header->entranceCharge = entranceCharge;

		time_t currentTime = time(0);
		if (auction->IsActive())
		{
			if (auction->GetAuctionTimer() < currentTime)
			{
				header->timer = 0;
			}
			else
			{
				header->timer = auction->GetAuctionTimer() - currentTime;
			}
		}
		else
		{
			if (auction->GetItem().GetItemTimer() < currentTime)
			{
				header->timer = 0;
			}
			else
			{
				header->timer = auction->GetItem().GetItemTimer() - currentTime;
			}
		}
		header->buyNowPrice = auction->GetBuyNowPrice();
		header->location  = auction->GetLocation().GetLocationString();
		header->ownerId = auction->GetCreatorId();

		// Determine the high bid info
		GetHighBidInfo(auction, header->highBid, header->highBidderId);

		if (type == AST_ByPlayerBids)
		{
			if (playerBid)
			{
				header->maxProxyBid = playerBid->GetMaxProxyBid();
				header->myBid = playerBid->GetBid();
			}
		}
		header->itemType =  auction->GetItem().GetCategory();
		header->resourceContainerClassCrc = auction->GetItem().GetResourceContainerClassCrc();
		header->flags = auction->GetFlags();
		if (auction->IsActive())
		{
			header->flags |= AUCTION_ACTIVE;
		}

		return header;
	}

	// ----------------------------------------------------------------------

	bool IsTextFilterMatch(
		Unicode::String const & itemName,
		Unicode::UnicodeStringVector const & textFilterAllTokens,
		Unicode::UnicodeStringVector const & textFilterAnyTokens)
	{
		bool isTextMatch = true;

		// We are doing a case insensitive search
		Unicode::String const lowerCaseName = Unicode::toLower(itemName);

		if (!textFilterAllTokens.empty())
		{
			// See if all of the tokens for the text filter can be found in the name
			Unicode::UnicodeStringVector::const_iterator i;
			for (i = textFilterAllTokens.begin(); i != textFilterAllTokens.end(); ++i)
			{
				if (lowerCaseName.find(*i) == Unicode::String::npos)
				{
					// We could not find a token so we do not match
					isTextMatch = false;
					break;
				}
			}
		}

		// If the name has all the required tokens, make sure it has
		// at least one of the "any" tokens
		if (isTextMatch)
		{
			if (!textFilterAnyTokens.empty())
			{
				// Assume we won't find a match
				isTextMatch = false;

				// See if any of the tokens for the text filter can be found in the name
				Unicode::UnicodeStringVector::const_iterator i;
				for (i = textFilterAnyTokens.begin(); i != textFilterAnyTokens.end(); ++i)
				{
					if (lowerCaseName.find(*i) != Unicode::String::npos)
					{
						// We found a token so we match
						isTextMatch = true;
						break;
					}
				}
			}
		}

		return isTextMatch;
	}

	// ----------------------------------------------------------------------

	bool IsPriceFilterMatch(
		Auction const * const auction,
		int const entranceCharge,
		int const priceFilterMin,
		int const priceFilterMax,
		bool const isPriceFilterToIncludeFee)
	{
		bool isPriceMatch = true;
		if ((priceFilterMin != 0) || (priceFilterMax != 0))
		{
			// Get the high bid info for the auction
			int       highBid;
			NetworkId highBidderId;
			GetHighBidInfo(auction, highBid, highBidderId);

			// Include the entrance fee for the price if necessary
			if (isPriceFilterToIncludeFee)
			{
				highBid += entranceCharge;
			}

			// Is this price less than the min specified?
			if ((priceFilterMin != 0) && (highBid < priceFilterMin))
			{
				isPriceMatch = false;
			}
			else
			{
				// Is this price greater than the max specified?
				if ((priceFilterMax != 0) && (highBid > priceFilterMax))
				{
					isPriceMatch = false;
				}
			}
		}

		return isPriceMatch;
	}

	// ----------------------------------------------------------------------

	struct GetItemAttributeDataRequest
	{
		std::string action;
		int requestingGameServerId;
		NetworkId requester;
		int gameObjectType;
		bool exactGameObjectTypeMatch;
		int throttleNumberItemsPerFrame;
		int numberItemsProcessed;
		NetworkId lastItemProcessed;

		// for GetItemAttributeData
		std::string outputFileName;
		std::map<int, std::pair<int, std::map<std::string, std::pair<int, std::string> > > > allItemAttributes;
		bool ignoreSearchableAttribute;

		// for GetItemAttributeDataValues
		std::string attributeName;
		int numberItemsMatchGameObjectType;
		std::map<std::string, int> attributeValue;
	};

	GetItemAttributeDataRequest * getItemAttributeDataRequest = nullptr;
	
	void processItemAttributeData(std::map<NetworkId, Auction *> const & auctions);

	// ----------------------------------------------------------------------

	void skipField(std::string const &source, unsigned int &pos, char const separator)
	{
		while (source[pos] && source[pos] != separator)
			++pos;
		if (source[pos] == separator)
			++pos;
	}

	// ----------------------------------------------------------------------

	void nextInt(std::string const &source, unsigned int &pos, int &ret, char const separator)
	{
		ret = atoi(source.c_str()+pos);
		skipField(source, pos, separator);
	}

	// ----------------------------------------------------------------------

	void nextString(std::string const &source, unsigned int &pos, std::string &ret, char const separator)
	{
		unsigned int oldPos = pos;
		while (source[pos] && source[pos] != separator)
			++pos;
		ret = source.substr(oldPos, pos-oldPos);
		if (source[pos] == separator)
			++pos;
	}

	// ----------------------------------------------------------------------

	void nextOid(std::string const &source, unsigned int &pos, NetworkId &ret, char const separator)
	{
		unsigned int oldPos = pos;
		skipField(source, pos, separator);
		ret = NetworkId(source.substr(oldPos, pos-oldPos));
	}

	// ----------------------------------------------------------------------

	void removeAuctionLocationFromList(std::map<NetworkId, AuctionLocation *> & auctionLocationList, const AuctionLocation * auctionLocation)
	{
		if (auctionLocation)
		{
			std::map<NetworkId, AuctionLocation *>::iterator const iterFind = auctionLocationList.find(auctionLocation->GetLocationId());
			if ((iterFind != auctionLocationList.end()) && (iterFind->second == auctionLocation))
			{
				auctionLocationList.erase(iterFind);
			}
		}
	}

};  // namespace AuctionMarketNamespace

// ======================================================================

void AuctionMarketNamespace::processItemAttributeData(std::map<NetworkId, Auction *> const & auctions)
{
	if (!getItemAttributeDataRequest)
		return;

	int count = 0;
	std::map<NetworkId, Auction *>::const_iterator iterAuction = auctions.upper_bound(getItemAttributeDataRequest->lastItemProcessed);
	for (; iterAuction != auctions.end(); ++iterAuction)
	{
		if (getItemAttributeDataRequest->action == "GetItemAttributeData")
		{
			bool proceed = true;
			if (getItemAttributeDataRequest->gameObjectType > 0)
			{
				if (getItemAttributeDataRequest->exactGameObjectTypeMatch)
				{
					if (iterAuction->second->GetItem().GetCategory() != getItemAttributeDataRequest->gameObjectType)
					{
						proceed = false;
					}
				}
				else
				{
					if (!GameObjectTypes::isTypeOf(iterAuction->second->GetItem().GetCategory(), getItemAttributeDataRequest->gameObjectType))
					{
						proceed = false;
					}
				}
			}

			if (proceed)
			{
				std::map<std::string, CommoditiesAdvancedSearchAttribute::SearchAttribute const *> const * skipAttribute = nullptr;
				std::map<std::string, std::string> const * skipAttributeAlias = nullptr;
				if (getItemAttributeDataRequest->ignoreSearchableAttribute)
				{
					std::map<std::string, CommoditiesAdvancedSearchAttribute::SearchAttribute const *> const & sa = CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(iterAuction->second->GetItem().GetCategory());
					if (!sa.empty())
					{
						skipAttribute = &sa;
					}

					if (skipAttribute)
					{
						std::map<std::string, std::string> const & saAlias = CommoditiesAdvancedSearchAttribute::getSearchAttributeNameAliasesForGameObjectType(iterAuction->second->GetItem().GetCategory());
						if (!saAlias.empty())
						{
							skipAttributeAlias = &saAlias;
						}
					}
				}

				std::pair<int, std::map<std::string, std::pair<int, std::string> > > & itemAttributeData = getItemAttributeDataRequest->allItemAttributes[iterAuction->second->GetItem().GetCategory()];
				++itemAttributeData.first;

				std::map<std::string, std::pair<int, std::string> > & itemAttributes = itemAttributeData.second;

				std::pair<int, std::map<std::string, std::pair<int, std::string> > > & parentItemAttributeData = getItemAttributeDataRequest->allItemAttributes[GameObjectTypes::getMaskedType(iterAuction->second->GetItem().GetCategory())];
				if (&itemAttributeData.first != &parentItemAttributeData.first)
					++parentItemAttributeData.first;

				std::map<std::string, std::pair<int, std::string> > & parentItemAttributes = parentItemAttributeData.second;

				std::vector<std::pair<std::string, Unicode::String> > const & attributes = iterAuction->second->GetAttributes();
				for (std::vector<std::pair<std::string, Unicode::String> >::const_iterator iterAttribute = attributes.begin(); iterAttribute != attributes.end(); ++iterAttribute)
				{
					if (skipAttribute && (skipAttribute->count(iterAttribute->first) >= 1))
					{
						continue;
					}

					if (skipAttributeAlias && (skipAttributeAlias->count(iterAttribute->first) >= 1))
					{
						continue;
					}

					std::map<std::string, std::pair<int, std::string> >::iterator const iterFindAttribute = itemAttributes.find(iterAttribute->first);
					if (iterFindAttribute != itemAttributes.end())
					{
						++iterFindAttribute->second.first;

						if (iterFindAttribute->second.second.empty())
							iterFindAttribute->second.second = Unicode::wideToNarrow(iterAttribute->second);
					}
					else
					{
						itemAttributes.insert(std::make_pair(iterAttribute->first, std::make_pair(1, Unicode::wideToNarrow(iterAttribute->second))));
					}

					if (&itemAttributeData.first != &parentItemAttributeData.first)
					{
						std::map<std::string, std::pair<int, std::string> >::iterator const iterFindParentAttribute = parentItemAttributes.find(iterAttribute->first);
						if (iterFindParentAttribute != parentItemAttributes.end())
						{
							++iterFindParentAttribute->second.first;

							if (iterFindParentAttribute->second.second.empty())
								iterFindParentAttribute->second.second = Unicode::wideToNarrow(iterAttribute->second);
						}
						else
						{
							parentItemAttributes.insert(std::make_pair(iterAttribute->first, std::make_pair(1, Unicode::wideToNarrow(iterAttribute->second))));
						}
					}
				}
			}
		}
		else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues")
		{
			bool proceed = true;
			if (getItemAttributeDataRequest->gameObjectType > 0)
			{
				if (getItemAttributeDataRequest->exactGameObjectTypeMatch)
				{
					if (iterAuction->second->GetItem().GetCategory() != getItemAttributeDataRequest->gameObjectType)
					{
						proceed = false;
					}
				}
				else
				{
					if (!GameObjectTypes::isTypeOf(iterAuction->second->GetItem().GetCategory(), getItemAttributeDataRequest->gameObjectType))
					{
						proceed = false;
					}
				}
			}

			if (proceed)
			{
				++getItemAttributeDataRequest->numberItemsMatchGameObjectType;

				std::vector<std::pair<std::string, Unicode::String> > const & attributes = iterAuction->second->GetAttributes();
				for (std::vector<std::pair<std::string, Unicode::String> >::const_iterator iterAttribute = attributes.begin(); iterAttribute != attributes.end(); ++iterAttribute)
				{
					if (iterAttribute->first == getItemAttributeDataRequest->attributeName)
					{
						std::string const value = Unicode::wideToNarrow(iterAttribute->second);
						std::map<std::string, int>::iterator const iterValue = getItemAttributeDataRequest->attributeValue.find(value);
						if (iterValue != getItemAttributeDataRequest->attributeValue.end())
						{
							++iterValue->second;
						}
						else
						{
							getItemAttributeDataRequest->attributeValue.insert(std::make_pair(value, 1));
						}
					}
				}
			}
		}

		++getItemAttributeDataRequest->numberItemsProcessed;

		++count;
		if (count >= getItemAttributeDataRequest->throttleNumberItemsPerFrame)
		{
			getItemAttributeDataRequest->lastItemProcessed = iterAuction->first;
			break;
		}
	}

	if (iterAuction == auctions.end())
	{
		std::string output;
		char buffer[2048];

		if (getItemAttributeDataRequest->action == "GetItemAttributeData")
		{
			for (std::map<int, std::pair<int, std::map<std::string, std::pair<int, std::string> > > >::const_iterator iterOutputGot = getItemAttributeDataRequest->allItemAttributes.begin(); iterOutputGot != getItemAttributeDataRequest->allItemAttributes.end(); ++iterOutputGot)
			{
				snprintf(buffer, sizeof(buffer)-1, "%s (count=%d)", GameObjectTypes::getCanonicalName(iterOutputGot->first).c_str(), iterOutputGot->second.first);
				buffer[sizeof(buffer)-1] = '\0';

				output += buffer;
				output += "\r\n";

				for (std::map<std::string, std::pair<int, std::string> >::const_iterator iterOutputAttribute = iterOutputGot->second.second.begin(); iterOutputAttribute != iterOutputGot->second.second.end(); ++iterOutputAttribute)
				{
					snprintf(buffer, sizeof(buffer)-1, "    %s (%s) (count=%d)", iterOutputAttribute->first.c_str(), iterOutputAttribute->second.second.c_str(), iterOutputAttribute->second.first);
					buffer[sizeof(buffer)-1] = '\0';

					output += buffer;
					output += "\r\n";
				}

				output += "\r\n";
			}

			if (output.empty())
			{
				output = "No Data";
			}
		}
		else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues")
		{
			snprintf(buffer, sizeof(buffer)-1, "%s (count=%d) attribute name=(%s)", GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), getItemAttributeDataRequest->numberItemsMatchGameObjectType, getItemAttributeDataRequest->attributeName.c_str());
			buffer[sizeof(buffer)-1] = '\0';

			output = buffer;
			output += "\r\n";

			for (std::map<std::string, int>::const_iterator iter = getItemAttributeDataRequest->attributeValue.begin(); iter != getItemAttributeDataRequest->attributeValue.end(); ++iter)
			{
				snprintf(buffer, sizeof(buffer)-1, "    (%s) (count=%d)", iter->first.c_str(), iter->second);
				buffer[sizeof(buffer)-1] = '\0';

				output += buffer;
				output += "\r\n";
			}
		}

		GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(getItemAttributeDataRequest->requestingGameServerId);
		if (gameServerConn)
		{
			if (getItemAttributeDataRequest->action == "GetItemAttributeData")
			{
				GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(getItemAttributeDataRequest->requester, getItemAttributeDataRequest->outputFileName), output));
				gameServerConn->send(msg, true);
			}
			else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues")
			{
				GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(getItemAttributeDataRequest->requester, output));
				gameServerConn->send(msg, true);
			}
		}

		delete getItemAttributeDataRequest;
		getItemAttributeDataRequest = nullptr;
	}
}

// ======================================================================

using namespace AuctionMarketNamespace;

// ======================================================================

AuctionMarket::AuctionMarket()  :
Singleton<AuctionMarket>(),
m_locationIdMap(),
m_playerVendorListMap(),
m_allBazaar(),
m_bazaarByPlanet(),
m_bazaarByRegion(),
m_allSearchableVendor(),
m_searchableVendorByPlanet(),
m_searchableVendorByRegion(),
m_auctions(),
m_auctionsCountByGameObjectType(),
m_auctionsCountByGameObjectTypeChanged(),
m_auctionCountMap(),
m_resourceTreeHierarchy(),
m_itemTypeMap(),
m_itemTypeMapVersionNumber(0),
m_resourceTypeMap(),
m_resourceTypeMapVersionNumber(0),
m_gameTime(0),
m_showAllDebugInfo(ConfigCommodityServer::getShowAllDebugInfo()),
m_completedAuctions(),
m_priorityQueueAuctionTimer(),
m_priorityQueueItemTimer()
{
	//
	// DO NOT DO ANYTHING HERE.  DO IT IN SingletonInialize()
	//
}

// ----------------------------------------------------------------------

void AuctionMarket::SingletonInialize()
{
	// ideally, these should be in the constructor, but they will result
	// in calling the Singleton's getInstance() method while the
	// Singleton is in the process of creating the Singleton, so
	// it tries to create another Singleton leading to an infinite loop;
	// we'll call this after the Singleton has been created
	GetLocation(std::string("PUBLIC_LOCATION"));

	// initialize list of auctions count by game object type
	GameObjectTypes::TypeStringMap const & gameObjectTypes = GameObjectTypes::getTypeStringMap();
	for (GameObjectTypes::TypeStringMap::const_iterator iter = gameObjectTypes.begin(); iter != gameObjectTypes.end(); ++iter)
	{
		m_auctionsCountByGameObjectType[iter->second] = 0;
		m_auctionsCountByGameObjectTypeChanged.insert(iter->second);
	}
}

// ----------------------------------------------------------------------

AuctionMarket::~AuctionMarket()
{
	//We need to delete the auction and auction location objects
	for (std::map<NetworkId, Auction *>::iterator i = m_auctions.begin(); i != m_auctions.end(); ++i)
	{
		delete (*i).second;
	}
	for (std::map<NetworkId, AuctionLocation *>::iterator i = m_locationIdMap.begin(); i != m_locationIdMap.end(); ++i)
	{
		delete (*i).second;
	}
}

// ----------------------------------------------------------------------

AuctionLocation *AuctionMarket::CreateLocation(const NetworkId & ownerId, const std::string & locationString, int entranceCharge)
{
	NetworkId loc_id = GetLocationId(locationString);
	AuctionLocation *auctionLocation = new AuctionLocation(loc_id, locationString, ownerId, 0, zeroNetworkId, 0, m_gameTime, 0, ACTIVE, true, entranceCharge);

	m_locationIdMap.insert(std::make_pair(loc_id, auctionLocation));
	if (ownerId != zeroNetworkId)
	{
		AddPlayerVendor(ownerId, loc_id, auctionLocation);
	}

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateLocationMessage.\n"));

	CMCreateLocationMessage msg(
		auctionLocation->GetLocationId(),
		auctionLocation->GetLocationString(),
		auctionLocation->GetOwnerId(),
		auctionLocation->GetSalesTax(),
		auctionLocation->GetSalesTaxBankId(),
		0,
		m_gameTime,
		0,
		ACTIVE,
		true,
		entranceCharge
	);
	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	if (dbServer)
		dbServer->send(msg, true);

	return auctionLocation;
}

// ----------------------------------------------------------------------

void AuctionMarket::InitializeFromDB()
{
	LoadCommoditiesMessage msg(1);
	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	LOG("CommoditiesServer", ("send LoadCommoditiesMessage to SwgDatabaseServer"));
	if (dbServer)
		dbServer->send(msg, true);
	else
		DEBUG_REPORT_LOG(true, ("[Commodities Server] : Cannot find dbServer to send LoadCommodities message.\n"));
}

// ----------------------------------------------------------------------

AuctionLocation &AuctionMarket::GetLocation(const NetworkId &locationId)
{
	std::map<NetworkId, AuctionLocation *>::const_iterator i =
		m_locationIdMap.find(locationId);
	if (i != m_locationIdMap.end())
	{
		return (* ((*i).second) );
	}

	DEBUG_REPORT_LOG(true, ("[Commodities Server] : Couldnot find location_id %s from auction_locations.\n", locationId.getValueString().c_str()));

	AuctionLocation *location = CreateLocation(zeroNetworkId, "PUBLIC_LOCATION", 0);
	return *location;
}

// ----------------------------------------------------------------------

AuctionLocation &AuctionMarket::GetLocation(const std::string &locationString)
{
	NetworkId locationId(GetLocationId(locationString));
	std::map<NetworkId, AuctionLocation *>::const_iterator i =
		m_locationIdMap.find(locationId);
	if (i != m_locationIdMap.end())
	{
		return (* ((*i).second) );
	}

	DEBUG_REPORT_LOG(true, ("[Commodities Server] : Couldnot find location_id %s from auction_locations.\n", locationId.getValueString().c_str()));

	AuctionLocation *location = CreateLocation(zeroNetworkId, locationString, 0);
	return *location;
}

// ----------------------------------------------------------------------

void AuctionMarket::ModifyAuctionCount(const NetworkId &  playerId, int delta)
{
	std::map<NetworkId, int>::iterator f = m_auctionCountMap.find(playerId);
	int currentAmount = 0;
	if (f != m_auctionCountMap.end())
	{
		currentAmount = (*f).second;
	}

	m_auctionCountMap[playerId] = (currentAmount + delta);
}

// ----------------------------------------------------------------------

bool AuctionMarket::HasOpenAuctionSlots(const NetworkId &  playerId)
{
	std::map<NetworkId, int>::iterator f = m_auctionCountMap.find(playerId);
	if (f != m_auctionCountMap.end())
	{
		if ((*f).second >= MAX_AUCTIONS_PER_PLAYER)
		{
			return false;
		}
	}
	return true;
}

// ----------------------------------------------------------------------

void AuctionMarket::AddPlayerVendor(const NetworkId & playerId, const NetworkId & vendorId, AuctionLocation * auctionLocation)
{
	(m_playerVendorListMap[playerId])[vendorId] = auctionLocation;
}

// ----------------------------------------------------------------------

void AuctionMarket::RemovePlayerVendor(const NetworkId & playerId, const NetworkId & vendorId)
{
	std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::iterator const iterPlayer = m_playerVendorListMap.find(playerId);
	if (iterPlayer != m_playerVendorListMap.end())
	{
		iterPlayer->second.erase(vendorId);
		if (iterPlayer->second.empty())
		{
			m_playerVendorListMap.erase(iterPlayer);
		}
	}
}

// ----------------------------------------------------------------------

int AuctionMarket::GetVendorCount(const NetworkId & playerId)
{
	std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::const_iterator const iterPlayer = m_playerVendorListMap.find(playerId);
	if (iterPlayer != m_playerVendorListMap.end())
	{
		return iterPlayer->second.size();
	}

	return 0;
}

// ----------------------------------------------------------------------

int AuctionMarket::GetItemCount(const NetworkId & playerId)
{
	int itemCount = 0;

	std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::const_iterator const iterPlayer = m_playerVendorListMap.find(playerId);
	if (iterPlayer != m_playerVendorListMap.end())
	{
		for (std::map<NetworkId, AuctionLocation *>::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation)
		{
			itemCount += iterAuctionLocation->second->GetAuctionItemCount();
		}
	}

	return itemCount;
}

// ----------------------------------------------------------------------

void AuctionMarket::AddAuctionToPriorityQueue(const Auction & auction)
{
	if (!(auction.GetFlags() & AUCTION_ALWAYS_PRESENT))
	{
		if (auction.IsActive() && (auction.GetAuctionTimer() > 0))
			m_priorityQueueAuctionTimer.insert(std::make_pair(auction.GetAuctionTimer(), auction.GetItem().GetItemId()));

		if (auction.GetItem().GetItemTimer() > 0)
			m_priorityQueueItemTimer.insert(std::make_pair(auction.GetItem().GetItemTimer(), auction.GetItem().GetItemId()));
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::AddAuctionLocationToPriorityQueue(const AuctionLocation & auctionLocation)
{
	m_priorityQueueAuctionLocation.insert(std::make_pair(auctionLocation.GetNextUpdateTime(), auctionLocation.GetLocationId()));
}

// ----------------------------------------------------------------------

void AuctionMarket::RemoveAuctionLocationFromPriorityQueue(const AuctionLocation & auctionLocation)
{
	m_priorityQueueAuctionLocation.erase(std::make_pair(auctionLocation.GetNextUpdateTime(), auctionLocation.GetLocationId()));
}

// ----------------------------------------------------------------------

void AuctionMarket::AddAuction(Auction *auction)
{
	assert(auction != nullptr);

	AuctionLocation &location = auction->GetLocation();
	if (!location.IsOwner(auction->GetItem().GetOwnerId()))
	{
		ModifyAuctionCount(auction->GetItem().GetOwnerId(), 1);
	}

	if ((auction->GetItem().GetItemTemplateId() != 0) && (auction->GetItem().GetCategory() != 0))
	{
		bool newItemType = false;

		std::set<int> & itemTypeList = m_itemTypeMap[auction->GetItem().GetCategory()];
		if (itemTypeList.count(auction->GetItem().GetItemTemplateId()) == 0)
		{
			newItemType = true;
			IGNORE_RETURN(itemTypeList.insert(auction->GetItem().GetItemTemplateId()));
		}

		if (newItemType)
		{
			++m_itemTypeMapVersionNumber;
			GenericValueTypeMessage<std::pair<int, std::pair<int, int> > > msg("CommoditiesItemTypeAdded", std::make_pair(m_itemTypeMapVersionNumber, std::make_pair(auction->GetItem().GetCategory(), auction->GetItem().GetItemTemplateId())));
			CommodityServer::getInstance().sendToAllGameServers(msg);
		}
	}

	m_auctions.insert(std::make_pair(auction->GetItem().GetItemId(), auction));

	std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory());
	std::map<std::string, int>::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType);
	if (iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end())
	{
		++iterAuctionsCountByGameObjectType->second;
		m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType);

		if (GameObjectTypes::isSubType(auction->GetItem().GetCategory()))
		{
			std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory()));
			std::map<std::string, int>::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType);
			if (iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end())
			{
				++iterAuctionsCountByParentGameObjectType->second;
				m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType);
			}
		}
	}

	location.AddAuction(auction);
	AddAuctionToPriorityQueue(*auction);

	if (auction->IsActive() && auction->IsSold())
		AddAuctionToCompletedAuctionsList(*auction);

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateAuctionMessage.\n"));
	LOG("CommoditiesServer", ("Player %s put item %s for sale at location %s for %d",
		auction->GetCreatorId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str(),
		auction->GetBuyNowPrice() + auction->GetMinBid()));
	LOG("CustomerService", ("Auction: Player %s put item %s for sale at location %s for %d",
		auction->GetCreatorId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str(),
		auction->GetBuyNowPrice() + auction->GetMinBid()));
	Unicode::String itemName(auction->GetItem().GetName());
	if (itemName.size() >= 1024)
	{
		itemName.assign(itemName, 0, 1023);
	}
	Unicode::String userDesc(auction->GetUserDescription());
	if (userDesc.size() >= 1024)
	{
		userDesc.assign(userDesc, 0, 1023);
	}
	CMCreateAuctionMessage msg(
		auction->GetCreatorId(),
		auction->GetMinBid(),
		auction->GetAuctionTimer(),
		auction->GetBuyNowPrice(),
		userDesc.size(),
		userDesc,
		auction->GetAttributes(),
		auction->GetLocation().GetLocationId(),
		auction->GetItem().GetItemId(),
		auction->GetItem().GetCategory(),
		auction->GetItem().GetItemTemplateId(),
		auction->GetItem().GetItemTimer(),
		itemName.size(),
		itemName,
		auction->GetItem().GetOwnerId(),
		(1 | auction->GetFlags()),
		auction->GetItem().GetSize());

	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	if (dbServer)
		dbServer->send(msg, true);
}

// ----------------------------------------------------------------------

void AuctionMarket::DestroyAuction(std::map<NetworkId, Auction *>::iterator &i)
{
	if (i != m_auctions.end())
	{
		Auction *auction = (*i).second;
		const NetworkId itemId = auction->GetItem().GetItemId();
		m_auctions.erase(i);

		std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory());
		std::map<std::string, int>::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType);
		if ((iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end()) && (iterAuctionsCountByGameObjectType->second > 0))
		{
			--iterAuctionsCountByGameObjectType->second;
			m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType);

			if (GameObjectTypes::isSubType(auction->GetItem().GetCategory()))
			{
				std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory()));
				std::map<std::string, int>::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType);
				if ((iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end()) && (iterAuctionsCountByParentGameObjectType->second > 0))
				{
					--iterAuctionsCountByParentGameObjectType->second;
					m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType);
				}
			}
		}

		AuctionLocation &location = auction->GetLocation();
		if (!location.IsOwner(auction->GetItem().GetOwnerId()))
		{
			ModifyAuctionCount(auction->GetItem().GetOwnerId(), -1);
		}
		location.RemoveAuction(auction);
		m_priorityQueueAuctionTimer.erase(std::make_pair(auction->GetAuctionTimer(), itemId));
		m_priorityQueueItemTimer.erase(std::make_pair(auction->GetItem().GetItemTimer(), itemId));

		delete auction;

		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteAuctionMessage.\n"));
		CMDeleteAuctionMessage msg(itemId);
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Item ItemId : %s.\n", msg.GetItemId().getValueString().c_str()));

		DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
		if (dbServer)
			dbServer->send(msg, true);
	}
	else
	{
		printf("Yo this is whacked\n");
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::UpdateLiveAuctions(int gameTime)
{
	if (getItemAttributeDataRequest)
		processItemAttributeData(m_auctions);

	// build the list of auctions that needs to be processed
	std::set<NetworkId> auctionsToBeProcessed;

	// auctions that have completed but not yet processed
	for (std::vector<NetworkId>::const_iterator iterCompletedAuctions = m_completedAuctions.begin(); iterCompletedAuctions != m_completedAuctions.end(); ++iterCompletedAuctions)
		auctionsToBeProcessed.insert(*iterCompletedAuctions);

	m_completedAuctions.clear();

	// auctions whose auction timer has expired
	for (std::set<std::pair<int, NetworkId> >::iterator iterAuctionTimer = m_priorityQueueAuctionTimer.begin(); iterAuctionTimer != m_priorityQueueAuctionTimer.end();)
	{
		if (gameTime >= (*iterAuctionTimer).first)
		{
			auctionsToBeProcessed.insert((*iterAuctionTimer).second);
			m_priorityQueueAuctionTimer.erase(iterAuctionTimer++);
		}
		else
		{
			break;
		}
	}

	// auctions whose item timer has expired
	for (std::set<std::pair<int, NetworkId> >::iterator iterItemTimer = m_priorityQueueItemTimer.begin(); iterItemTimer != m_priorityQueueItemTimer.end();)
	{
		if (gameTime > (*iterItemTimer).first)
		{
			auctionsToBeProcessed.insert((*iterItemTimer).second);
			m_priorityQueueItemTimer.erase(iterItemTimer++);
		}
		else
		{
			break;
		}
	}

	// process auctions needing to be processed
	std::set<NetworkId>::const_iterator iterAuctionsToBeProcessed;
	std::vector<std::map<NetworkId, Auction *>::iterator> completedAuctions;
	std::map<NetworkId, Auction *>::iterator auctionsIterator;

	for (iterAuctionsToBeProcessed = auctionsToBeProcessed.begin(); iterAuctionsToBeProcessed != auctionsToBeProcessed.end(); ++iterAuctionsToBeProcessed)
	{
		auctionsIterator = m_auctions.find(*iterAuctionsToBeProcessed);
		if (auctionsIterator != m_auctions.end())
		{
			if ((*auctionsIterator).second->Update(gameTime) == false)
			{
				//item is finished.
				const AuctionItem &item = (*auctionsIterator).second->GetItem();
				const AuctionLocation &location = (*auctionsIterator).second->GetLocation();
				OnItemExpired(item.GetOwnerId(), item.GetItemId(),
					item.GetNameLength(), item.GetName(),
					location.GetLocationString(), location.GetLocationId());
				completedAuctions.push_back(auctionsIterator);
			}
		}
	}

	std::vector<std::map<NetworkId, Auction *>::iterator>::iterator ri =
		completedAuctions.begin();
	while (ri != completedAuctions.end())
	{
		auctionsIterator = (*ri);
		LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction has expired (gametime: %d, itemTimer: %d).", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), gameTime, (*auctionsIterator).second->GetItem().GetItemTimer()));
		LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction has expired (gametime: %d, itemTimer: %d).", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), gameTime, (*auctionsIterator).second->GetItem().GetItemTimer()));
		DestroyAuction(auctionsIterator);
		++ri;
	}

	std::list<AuctionLocation *> auctionLocationsToBeProcessed;
	{
		for (std::set<std::pair<int, NetworkId> >::iterator iterAuctionLocationToBeProcessed = m_priorityQueueAuctionLocation.begin(); iterAuctionLocationToBeProcessed != m_priorityQueueAuctionLocation.end();)
		{
			if (gameTime > (*iterAuctionLocationToBeProcessed).first)
			{
				std::map<NetworkId, AuctionLocation *>::iterator iterFind = m_locationIdMap.find((*iterAuctionLocationToBeProcessed).second);
				if (iterFind != m_locationIdMap.end())
				{
					auctionLocationsToBeProcessed.push_back(iterFind->second);
				}

				m_priorityQueueAuctionLocation.erase(iterAuctionLocationToBeProcessed++);
			}
			else
			{
				break;
			}
		}
	}

	for (std::list<AuctionLocation *>::iterator locationIterator = auctionLocationsToBeProcessed.begin(); locationIterator != auctionLocationsToBeProcessed.end(); ++locationIterator)
	{
		if ((*locationIterator)->IsVendorMarket())
		{
			VendorStatusCode status = (VendorStatusCode) (*locationIterator)->GetStatus();
			VendorStatusCode newStatus = status;
			int emptyDate = (*locationIterator)->GetEmptyDate();
			int lastAccessDate = (*locationIterator)->GetLastAccessDate();
			int inactiveDate = (*locationIterator)->GetInactiveDate();
			int newEmptyDate = -1, newLastAccessDate = -1, newInactiveDate = -1;
			switch (status) {
				case ACTIVE:
					if ((*locationIterator)->GetAuctionItemCount() == 0)
					{
						newStatus = EMPTY;
						newEmptyDate = m_gameTime;
					}
					else
					{
						int const unaccessedTime = lastAccessDate + (ConfigCommodityServer::getMinutesActiveToUnaccessed() * 60);
						if (m_gameTime >= unaccessedTime)
						{
							newStatus = UNACCESSED;
						}
						else
						{
							(*locationIterator)->SetNextUpdateTime(unaccessedTime);
						}
					}
					break;
				case EMPTY:
					{
						int const endangeredTime = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60);
						int const emptyAndUnaccessedTime = lastAccessDate + (ConfigCommodityServer::getMinutesUnaccessedToEndangered() * 60);
						if (m_gameTime >= endangeredTime)
						{
							newStatus = ENDANGERED;
							newInactiveDate = m_gameTime;
						}
						else if (m_gameTime >= emptyAndUnaccessedTime)
						{
							newStatus = EMPTY_AND_UNACCESSED;
						}
						else
						{
							(*locationIterator)->SetNextUpdateTime((endangeredTime < emptyAndUnaccessedTime) ? endangeredTime : emptyAndUnaccessedTime);
						}
					}
					break;
				case UNACCESSED:
					{
						int const endangeredTime = lastAccessDate + ((ConfigCommodityServer::getMinutesActiveToUnaccessed() + ConfigCommodityServer::getMinutesUnaccessedToEndangered()) * 60);
						if (m_gameTime >= endangeredTime)
						{
							newStatus = ENDANGERED;
							newInactiveDate = m_gameTime;
						}
						else if (emptyDate > 0)
						{
							int const emptyAndUnaccessedTime = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60);
							if (m_gameTime >= emptyAndUnaccessedTime)
							{
								newStatus = EMPTY_AND_UNACCESSED;
							}
							else
							{
								(*locationIterator)->SetNextUpdateTime((endangeredTime < emptyAndUnaccessedTime) ? endangeredTime : emptyAndUnaccessedTime);
							}
						}
						else
						{
							(*locationIterator)->SetNextUpdateTime(endangeredTime);
						}
					}
					break;
				case EMPTY_AND_UNACCESSED:
					{
						int const endangeredTime1 = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60);
						int const endangeredTime2 = lastAccessDate + ((ConfigCommodityServer::getMinutesActiveToUnaccessed() + ConfigCommodityServer::getMinutesUnaccessedToEndangered()) * 60);
						if ((m_gameTime >= endangeredTime1) || (m_gameTime >= endangeredTime2))
						{
							newStatus = ENDANGERED;
							newInactiveDate = m_gameTime;
						}
						else
						{
							(*locationIterator)->SetNextUpdateTime((endangeredTime1 < endangeredTime2) ? endangeredTime1 : endangeredTime2);
						}
					}
					break;
				case ENDANGERED:
					{
						int const removedTime = inactiveDate + (ConfigCommodityServer::getMinutesEndangeredToRemoved() * 60);
						if (m_gameTime >= removedTime)
						{
							newStatus = REMOVED;
						}
						else
						{
							(*locationIterator)->SetNextUpdateTime(removedTime);
						}
					}
					break;
				case REMOVED:
					newStatus = REMOVED;
			}
			if (status != newStatus)
			{
				(*locationIterator)->Update(newEmptyDate, newLastAccessDate, newInactiveDate, newStatus);
				LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to %s", (*locationIterator)->GetLocationId().getValueString().c_str(), (*locationIterator)->GetOwnerId().getValueString().c_str(), vendorStatus[status], vendorStatus[newStatus]));
				LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to %s", (*locationIterator)->GetLocationId().getValueString().c_str(), (*locationIterator)->GetOwnerId().getValueString().c_str(), vendorStatus[status], vendorStatus[newStatus]));
				AuctionResultCode arc;
				switch (newStatus) {
					case EMPTY:
						arc = ARC_VendorStatusEmpty;
						break;
					case UNACCESSED:
						arc = ARC_VendorUnaccessed;
						break;
					case EMPTY_AND_UNACCESSED:
						if (status == EMPTY)
							arc = ARC_VendorUnaccessed;
						else
							arc = ARC_VendorStatusEmpty;
						break;
					case ENDANGERED:
						arc = ARC_VendorEndangered;
						LOG("CommoditiesServer", ("Vendor %s becomes endangered being removed from game.",
							(*locationIterator)->GetLocationId().getValueString().c_str()));
						LOG("CuxtomerService", ("Vendor: Vendor %s becomes endangered being removed from game.",
							(*locationIterator)->GetLocationId().getValueString().c_str()));
						break;
					case REMOVED:
						arc = ARC_VendorRemoved;
						LOG("CommoditiesServer", ("Vendor %s will be removed from game due to empty or inactivity.",
							(*locationIterator)->GetLocationId().getValueString().c_str()));
						LOG("CustomerService", ("Vendor: Vendor %s will be removed from game due to empty or inactivity.",
							(*locationIterator)->GetLocationId().getValueString().c_str()));
						break;
					default:
						// newStatus is ACTIVE, which is impossible.
						// code added to avoid error in release build
						arc = ARC_Success;
				}
				OnVendorStatusChange(-1, (*locationIterator)->GetLocationId(), arc);
			}
		}
	}

	// if a processed auction is still valid (i.e. not yet deleted),
	// add it back to the priority queue so it can be processed
	// at its next timer expiration time
	for (iterAuctionsToBeProcessed = auctionsToBeProcessed.begin(); iterAuctionsToBeProcessed != auctionsToBeProcessed.end(); ++iterAuctionsToBeProcessed)
	{
		auctionsIterator = m_auctions.find(*iterAuctionsToBeProcessed);

		if (auctionsIterator != m_auctions.end())
		{
			AddAuctionToPriorityQueue(*(auctionsIterator->second));

			if (auctionsIterator->second->IsActive() && auctionsIterator->second->IsSold())
				AddAuctionToCompletedAuctionsList(*(auctionsIterator->second));
		}
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::DestroyExpiredItems(int gameTime)
{
}

// ----------------------------------------------------------------------

void AuctionMarket::Update(int gameTime)
{
	m_gameTime = time(0);
	DestroyExpiredItems(gameTime);
	UpdateLiveAuctions(gameTime);
}

// ======================================================================
//
// AuctionMarket Network Message Handlers
//
// ======================================================================

void AuctionMarket::AddAuction(const AddAuctionMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : MinimumBid : %d.\n", message.GetMinimumBid()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : AuctionTimer : %d.\n", message.GetAuctionTimer()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemNameLength : %d.\n", message.GetItemNameLength()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemType : %d.\n", message.GetItemType()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemTemplateId : %d.\n", message.GetItemTemplateId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ExpireTimer : %d.\n", message.GetExpireTimer()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Flags : %d.\n", message.GetFlags()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobLength : %d.\n", message.GetOobLength()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobActualLength : %d.\n", message.GetOobData().size()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobData : %s.\n", Unicode::wideToNarrow(message.GetOobData()).c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemSize : %d.\n", message.GetItemSize()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Vendor Limit : %d.\n", message.GetVendorLimit()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Vendor Item Limit : %d.\n", message.GetVendorItemLimit()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, Auction *>::iterator exists = m_auctions.find(
		message.GetItemId());
	AuctionLocation &auctionLocation = GetLocation(std::string(message.GetLocation()));
	if (exists != m_auctions.end())
	{
		OnAddAuction(message.GetTrackId(), ARC_AuctionAlreadyExists,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			auctionLocation.GetOwnerId(),
			auctionLocation.GetLocationString());
		return;
	}
	if (!auctionLocation.IsOwner(message.GetOwnerId()) && !HasOpenAuctionSlots(message.GetOwnerId()))
	{
		OnAddAuction(message.GetTrackId(), ARC_TooManyAuctions,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			auctionLocation.GetOwnerId(),
			auctionLocation.GetLocationString());
		return;
	}

	if (auctionLocation.IsVendorMarket())
	{
		OnAddAuction(message.GetTrackId(), ARC_AuctionAtVendorMarket,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			auctionLocation.GetOwnerId(),
			auctionLocation.GetLocationString());
		return;
	}
	int itemSize = (message.GetItemSize() <2) ? 1 : (message.GetItemSize()-1);

	Auction *auction = new Auction(
		message.GetOwnerId(),
		message.GetMinimumBid(),
		message.GetAuctionTimer(),
		message.GetItemId(),
		message.GetItemNameLength(),
		message.GetItemName(),
		message.GetItemType(),
		message.GetItemTemplateId(),
		message.GetExpireTimer(),
		itemSize,
		auctionLocation,
		message.GetFlags(),
		0,
		message.GetUserDescriptionLength(),
		message.GetUserDescription(),
		0,
		Unicode::emptyString,
		message.GetAttributes());

	AddAuction(auction);

	OnAddAuction(message.GetTrackId(), ARC_Success,
		message.GetResponseId(),
		message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
		auctionLocation.GetOwnerId(),
		auctionLocation.GetLocationString());

}

// ----------------------------------------------------------------------

void AuctionMarket::AddImmediateAuction(const AddImmediateAuctionMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : AuctionTimer : %d.\n", message.GetAuctionTimer()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : GetPrice : %d.\n", message.GetPrice()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemNameLength : %d.\n", message.GetItemNameLength()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemType : %d.\n", message.GetItemType()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemTemplateId : %d.\n", message.GetItemTemplateId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ExpireTimer : %d.\n", message.GetExpireTimer()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Flags : %d.\n", message.GetFlags()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobLength : %d.\n", message.GetOobLength()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobActualLength : %d.\n", message.GetOobData().size()));
//	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobData : %s.\n", Unicode::wideToNarrow(message.GetOobData()).c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemSize : %d.\n", message.GetItemSize()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit : %d.\n", message.GetVendorLimit()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit : %d.\n", message.GetVendorItemLimit()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, Auction *>::iterator exists = m_auctions.find(
		message.GetItemId());

	// force a 30 day stock/restock timer for player vendors.
	int auctionTimer = (ConfigCommodityServer::getMinutesVendorAuctionTimer() * 60) + time(0);
	// force the expire timer to be 30 days after the auction timer has finished
	// The expire timer should be large to allow for time to sit in the stockroom before it is deleted.
	int expireTimer = auctionTimer + (ConfigCommodityServer::getMinutesVendorItemTimer() * 60);

	if (message.GetFlags() & AUCTION_VENDOR_TRANSFER)
	{
		if (exists == m_auctions.end())
		{
			OnAddAuction(message.GetTrackId(), ARC_AuctionDoesNotExist,
				message.GetResponseId(),
				message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			return;
		}
		Auction *oldAuction = (*exists).second;
		if (oldAuction->GetItem().GetOwnerId() != message.GetOwnerId())
		{
			OnAddAuction(message.GetTrackId(), ARC_NotItemOwner,
				message.GetResponseId(),
				message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			return;
		}
		AuctionLocation &location = oldAuction->GetLocation();

		// This catches the restock path
		if( location.IsVendorMarket() )
		{
			// check the player's vendor limit
			if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit())
			{
				OnAddAuction(message.GetTrackId(),
					ARC_AuctionVendorLimitExceeded,
					message.GetResponseId(),
					message.GetItemId(),
					message.GetOwnerId(),
					message.GetOwnerName(),
					zeroNetworkId,
					std::string());
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit()));
				return;
			}
			if (GetItemCount(message.GetOwnerId()) >= message.GetVendorItemLimit())
			{
				OnAddAuction(message.GetTrackId(),
					ARC_AuctionVendorItemLimitExceeded,
					message.GetResponseId(),
					message.GetItemId(),
					message.GetOwnerId(),
					message.GetOwnerName(),
					zeroNetworkId,
					std::string());
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetItemCount(message.GetOwnerId()), message.GetVendorItemLimit()));
				return;
			}
		}
		// If this is not a player vendor, then use the values sent in from the message
		else
		{
			auctionTimer = message.GetAuctionTimer();
			expireTimer = message.GetExpireTimer();
		}

		// cannot use "relist" on an item bought as a vendor offer;
		// must use "sell" and enter a new selling price for the item
		if ((oldAuction->GetFlags() & AUCTION_OFFERED_ITEM) && (message.GetPrice() < 0))
		{
			OnAddAuction(message.GetTrackId(),
				ARC_InvalidBid,
				message.GetResponseId(),
				message.GetItemId(),
				message.GetOwnerId(),
				message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			return;
		}

		// make sure price is valid
		int const price = ((message.GetPrice() >= 0) ? message.GetPrice() : oldAuction->GetBuyNowPrice());
		if (price < 0)
		{
			OnAddAuction(message.GetTrackId(),
				ARC_InvalidBid,
				message.GetResponseId(),
				message.GetItemId(),
				message.GetOwnerId(),
				message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			return;
		}

		Auction *auction = new Auction(
			message.GetOwnerId(),
			0, auctionTimer,
			message.GetItemId(),
			((message.GetItemNameLength() > 0) ? message.GetItemNameLength() : oldAuction->GetItem().GetNameLength()),
			((message.GetItemNameLength() > 0) ? message.GetItemName() : oldAuction->GetItem().GetName()),
			oldAuction->GetItem().GetCategory(),
			oldAuction->GetItem().GetItemTemplateId(),
			expireTimer,
			oldAuction->GetItem().GetSize(),
			oldAuction->GetLocation(),
			(oldAuction->GetFlags() & (~AUCTION_OFFERED_ITEM)),
			price,
			((message.GetPrice() >= 0) ? message.GetUserDescriptionLength() : oldAuction->GetUserDescriptionLength()),
			((message.GetPrice() >= 0) ? message.GetUserDescription() : oldAuction->GetUserDescription()),
			oldAuction->GetOobLength(),
			oldAuction->GetOobData(),
			oldAuction->GetAttributes());

		LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction is about to be relisted.", (*exists).second->GetItem().GetItemId().getValueString().c_str()));
		LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction is about to be relisted.", (*exists).second->GetItem().GetItemId().getValueString().c_str()));

		DestroyAuction(exists);

		AddAuction(auction);

		OnAddAuction(message.GetTrackId(), ARC_Success,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			location.GetOwnerId(),
			location.GetLocationString());
		if (location.IsVendorMarket() && location.IsOwner(message.GetOwnerId()))
		{
			if (location.GetStatus() != ACTIVE)
			{
				LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", location.GetLocationId().getValueString().c_str(), location.GetOwnerId().getValueString().c_str(), vendorStatus[location.GetStatus()]));
				LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", location.GetLocationId().getValueString().c_str(), location.GetOwnerId().getValueString().c_str(), vendorStatus[location.GetStatus()]));
			}
			location.Update(0, m_gameTime, 0, ACTIVE);
		}
		return;
	}

	int itemSize = (message.GetItemSize() <2) ? 1 : (message.GetItemSize()-1);
	AuctionLocation &auctionLocation = GetLocation(std::string(message.GetLocation()));
	if (exists != m_auctions.end())
	{
		static Unicode::String const emptyUnicodeString;
		if (message.GetOwnerName() == "Restoring object")
		{
			DestroyAuction(exists);
			Auction *auction = new Auction(
				message.GetOwnerId(),
				0,
				auctionTimer,
				message.GetItemId(),
				message.GetItemNameLength(),
				message.GetItemName(),
				message.GetItemType(),
				message.GetItemTemplateId(),
				expireTimer,
				itemSize,
				auctionLocation,
				message.GetFlags(),
				message.GetPrice(),
				message.GetUserDescriptionLength(),
				message.GetUserDescription(),
				0,
				emptyUnicodeString,
				message.GetAttributes());
			AddAuction(auction);
		}
		OnAddAuction(message.GetTrackId(), ARC_AuctionAlreadyExists,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			auctionLocation.GetOwnerId(),
			auctionLocation.GetLocationString());
		return;
	}

	if( auctionLocation.IsVendorMarket()  && auctionLocation.IsOwner(message.GetOwnerId()))
	{
		// check the player's vendor limit
		if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit())
		{
			OnAddAuction(message.GetTrackId(),
				ARC_AuctionVendorLimitExceeded,
				message.GetResponseId(),
				message.GetItemId(),
				message.GetOwnerId(),
				message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit()));
			return;
		}
		if (GetItemCount(message.GetOwnerId()) >= message.GetVendorItemLimit())
		{
			OnAddAuction(message.GetTrackId(),
				ARC_AuctionVendorItemLimitExceeded,
				message.GetResponseId(),
				message.GetItemId(),
				message.GetOwnerId(),
				message.GetOwnerName(),
				zeroNetworkId,
				std::string());
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetItemCount(message.GetOwnerId()), message.GetVendorItemLimit()));
			return;
		}
	}
	else if (!HasOpenAuctionSlots(message.GetOwnerId()))
	{
		OnAddAuction(message.GetTrackId(), ARC_TooManyAuctions,
			message.GetResponseId(),
			message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
			auctionLocation.GetOwnerId(),
			auctionLocation.GetLocationString());
		return;
	}

	// If this is not a player vendor, then use the values sent in from the message
	if( !auctionLocation.IsVendorMarket() )
	{
		auctionTimer = message.GetAuctionTimer();
		expireTimer = message.GetExpireTimer();
	}

	static Unicode::String const emptyUnicodeString;
	Auction *auction = new Auction(
		message.GetOwnerId(),
		0, auctionTimer,
		message.GetItemId(),
		message.GetItemNameLength(),
		message.GetItemName(),
		message.GetItemType(),
		message.GetItemTemplateId(),
		expireTimer,
		itemSize,
		auctionLocation,
		message.GetFlags(),
		message.GetPrice(),
		message.GetUserDescriptionLength(),
		message.GetUserDescription(),
		0,
		emptyUnicodeString,
		message.GetAttributes());

	AddAuction(auction);

	OnAddAuction(message.GetTrackId(), ARC_Success,
		message.GetResponseId(),
		message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(),
		auctionLocation.GetOwnerId(),
		auctionLocation.GetLocationString());
	if (auctionLocation.IsVendorMarket() && auctionLocation.IsOwner(message.GetOwnerId()))
	{
		if (auctionLocation.GetStatus() != ACTIVE)
		{
			LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", auctionLocation.GetLocationId().getValueString().c_str(), auctionLocation.GetOwnerId().getValueString().c_str(), vendorStatus[auctionLocation.GetStatus()]));
			LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", auctionLocation.GetLocationId().getValueString().c_str(), auctionLocation.GetOwnerId().getValueString().c_str(), vendorStatus[auctionLocation.GetStatus()]));
		}
		auctionLocation.Update(0, m_gameTime, 0, ACTIVE);
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::AddBid(const AddBidMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetAuctionId : %s.\n", message.GetAuctionId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetPlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetBid : %d.\n", message.GetBid()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetMaxProxyBid : %d.\n", message.GetMaxProxyBid()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetPlayerName	: %s.\n", message.GetPlayerName().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(
		message.GetAuctionId());
	if (iter == m_auctions.end())
	{
		OnAddBid(message.GetTrackId(), ARC_AuctionDoesNotExist,
			message.GetResponseId(), zeroNetworkId, message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0,
			message.GetMaxProxyBid(), "PUBLIC_VENDOR",
			0, Unicode::String(), 0, zeroNetworkId);
		return;
	}
	if (!(*iter).second->IsActive())
	{
		OnAddBid(message.GetTrackId(), ARC_AuctionDoesNotExist,
			message.GetResponseId(), zeroNetworkId, message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0,
			message.GetMaxProxyBid(), "PUBLIC_VENDOR",
			0, Unicode::String(), 0, zeroNetworkId);
		return;
	}

	Auction *auction = (*iter).second;

	// if it's an immediate auction, the bid value must be
	// exactly the same as the buy now price + sales tax;
	// the client won't let you enter a different bid price
	// for an immediate auction, but a player could use a
	// hacked client to change the bid price, and we need
	// to catch that, and generate a customer service log
	// if the bid price is not the same as the buy now
	// price + sales tax; note that we could also get here
	// legitimately if the sales tax was changed but the
	// client had not refreshed the auction to reflect
	// the price with the new sales tax
	if (auction->IsImmediate() && ((message.GetBid() != auction->GetBuyNowPriceWithSalesTax()) || (message.GetMaxProxyBid() != auction->GetBuyNowPriceWithSalesTax())))
	{
		std::string itemName = Unicode::wideToNarrow(auction->GetItem().GetName());

		LOG("CustomerService", ("Auction: Player %s (%s) sent an invalid bid (bid=%d, max proxy bid=%d) for immediate auction %s (%s) (buy now price=%d, buy now price with sales tax=%d) at location (%s)",
			message.GetPlayerName().c_str(), message.GetPlayerId().getValueString().c_str(),
			message.GetBid(), message.GetMaxProxyBid(),
			auction->GetItem().GetItemId().getValueString().c_str(), itemName.c_str(),
			auction->GetBuyNowPrice(), auction->GetBuyNowPriceWithSalesTax(),
			auction->GetLocation().GetLocationString().c_str()));

		OnAddBid(message.GetTrackId(), ARC_InvalidBid,
			message.GetResponseId(), zeroNetworkId, message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0,
			message.GetMaxProxyBid(), "PUBLIC_VENDOR",
			0, Unicode::String(), 0, zeroNetworkId);

		return;
	}

	int	oldHighBidAmount = auction->GetHighBidAmount();

	AuctionResultCode result = auction->AddBid(
		message.GetPlayerId(), message.GetBid(), message.GetMaxProxyBid());

	if (result == ARC_SuccessPermanentAuction)
	{
		//printf("AddBid is PermanentAuction.\n");
		OnPermanentAuctionPurchased(
			message.GetTrackId(),
			auction->GetCreatorId(), message.GetPlayerId(),
			message.GetBid(), message.GetAuctionId(),
			auction->GetLocation().GetLocationString(),
			auction->GetItem().GetNameLength(),
			auction->GetItem().GetName(),
			auction->GetAttributes());

		OnAddBid(message.GetTrackId(), result,
			message.GetResponseId(), auction->GetCreatorId(),
			message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, message.GetBid(),
			0, message.GetMaxProxyBid(),
			auction->GetLocation().GetLocationString(),
			auction->GetItem().GetNameLength(), auction->GetItem().GetName(), 0, zeroNetworkId);

		return;
	}

	const AuctionBid *highBid = auction->GetHighBid();

	if ((highBid) &&
		((result == ARC_Success) || (oldHighBidAmount < highBid->GetBid())))
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateAuctionBidMessage.\n"));

		CMCreateAuctionBidMessage msg(
			auction->GetItem().GetItemId(),
			highBid->GetBidderId(),
			highBid->GetBid(),
			highBid->GetMaxProxyBid()
		);
		DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
		if (dbServer)
			dbServer->send(msg, true);
	}

	const AuctionBid *previousBid = auction->GetPreviousBid();
	NetworkId previousBidder = zeroNetworkId;
	int previousBidAmount = 0;
	int maxProxyBid = message.GetMaxProxyBid();
	int salesTaxAmount = 0;
	NetworkId bankId = zeroNetworkId;

	if (previousBid)
	{
		previousBidder = previousBid->GetBidderId();
		previousBidAmount = previousBid->GetMaxProxyBid();
		//printf("AddBid is Auction.\n");
	}
	if (auction->GetBuyNowPrice() != 0)
	{
		//its an instant auction, set the previous bidder to -1 to signify
		previousBidder = negOneNetworkId;
		maxProxyBid = auction->GetBuyNowPrice();
		salesTaxAmount = auction->GetBuyNowPriceWithSalesTax() - auction->GetBuyNowPrice();
		bankId = auction->GetLocation().GetSalesTaxBankId();
		//printf("AddBid is Immediate.\n");
	}

	OnAddBid(message.GetTrackId(), result,
		message.GetResponseId(), auction->GetCreatorId(),
		message.GetAuctionId(),
		message.GetPlayerId(), previousBidder, message.GetBid(),
		previousBidAmount, maxProxyBid,
		auction->GetLocation().GetLocationString(),
		auction->GetItem().GetNameLength(), auction->GetItem().GetName(),
		salesTaxAmount, bankId);
	LOG("CommoditiesServer", ("Player %s put a bid %d on item %s",
		message.GetPlayerId().getValueString().c_str(),
		message.GetBid(),
		message.GetAuctionId().getValueString().c_str()));
	LOG("CustomerService", ("Auction: Player %s put a bid %d on item %s",
		message.GetPlayerId().getValueString().c_str(),
		message.GetBid(),
		message.GetAuctionId().getValueString().c_str()));

	AuctionLocation &loc = auction->GetLocation();
	if (loc.IsVendorMarket() && (!loc.IsOwner(message.GetPlayerId())))
	{
		if (loc.GetStatus() != ACTIVE)
		{
			LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", loc.GetLocationId().getValueString().c_str(), loc.GetOwnerId().getValueString().c_str(), vendorStatus[loc.GetStatus()]));
			LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", loc.GetLocationId().getValueString().c_str(), loc.GetOwnerId().getValueString().c_str(), vendorStatus[loc.GetStatus()]));
		}
		loc.Update(0, m_gameTime, 0, ACTIVE);
	}

	// if an item got bought off a vendor, we must send the auction
	// complete/expire message to the game server where the item is
	// bought, because that game server is where some additional
	// processing/validation needs to be done for this transaction;
	// we store the game server id in Auction, and in Auction::Update(),
	// it will send the auction complete/expire message to the game server
	if (loc.IsVendorMarket() && auction->IsImmediate() && auction->IsSold())
		auction->SetTrackId(message.GetTrackId());
}

// ----------------------------------------------------------------------

void AuctionMarket::CancelAuction(const CancelAuctionMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(message.GetAuctionId());
	if (iter == m_auctions.end())
	{
		OnCancelAuction(message.GetTrackId(), ARC_AuctionDoesNotExist,
			message.GetResponseId(), message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, 0, "PUBLIC_LOCATION");
		return;
	}

	Auction *auction = (*iter).second;
	LOG("CommoditiesServer", ("Player %s canceled auction for item %s at location %s",
		auction->GetItem().GetOwnerId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str()));
	LOG("CustomerService", ("Auction: Player %s canceled auction for item %s at location %s",
		auction->GetItem().GetOwnerId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str()));

	if (auction->GetLocation().IsVendorMarket() &&  auction->GetLocation().IsOwner(message.GetPlayerId()))
	{
		if (auction->GetItem().GetOwnerId() == message.GetPlayerId())
		{
			if (auction->IsActive())
			{
				//The vendor owner is cancelling his own sale
				OnCancelAuction(message.GetTrackId(), ARC_Success,
								message.GetResponseId(), message.GetAuctionId(),
								message.GetPlayerId(), zeroNetworkId, 0,
								auction->GetLocation().GetLocationString());
				auction->Expire(false, false, message.GetTrackId());
				if (auction->GetLocation().GetStatus() != ACTIVE)
				{
					LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", auction->GetLocation().GetLocationId().getValueString().c_str(), auction->GetLocation().GetOwnerId().getValueString().c_str(), vendorStatus[auction->GetLocation().GetStatus()]));
					LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", auction->GetLocation().GetLocationId().getValueString().c_str(), auction->GetLocation().GetOwnerId().getValueString().c_str(), vendorStatus[auction->GetLocation().GetStatus()]));
				}
				auction->GetLocation().Update(0, m_gameTime, 0, ACTIVE);
			}
			else
			{
				OnCancelAuction(message.GetTrackId(), ARC_VendorOwnerCanceledCompletedAuction,
								message.GetResponseId(), message.GetAuctionId(),
								message.GetPlayerId(), zeroNetworkId, 0,
								auction->GetLocation().GetLocationString());
				return;

			}
		}
		// make sure the sale is still active before deciding it's the owner refusing to buy an offer.
		// Fixes a crediting duping exploit where the owner
		// of the vendor withdraws a sale after someone buys it.
		else if( auction->GetItem().GetOwnerId() != message.GetPlayerId() && !auction->IsActive() )
		{
			OnCancelAuction(message.GetTrackId(), ARC_VendorOwnerCanceledCompletedAuction,
				message.GetResponseId(), message.GetAuctionId(),
				message.GetPlayerId(), zeroNetworkId, 0,
				auction->GetLocation().GetLocationString());
			return;
		}
		// owner of the vendor is refusing an offer to his vendor
		else
		{
			//The vendor owner doesn't want your crap!
			OnVendorRefuseItem(message.GetTrackId(), ARC_Success,
				message.GetResponseId(), message.GetAuctionId(),
				message.GetPlayerId(), auction->GetCreatorId());
			auction->Expire(false, false, message.GetTrackId());
		}
		return;
	}
	else if (message.GetPlayerId() != auction->GetCreatorId())
	{
		OnCancelAuction(message.GetTrackId(), ARC_NotItemOwner,
			message.GetResponseId(), message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, 0,
			auction->GetLocation().GetLocationString());
		return;
	}
	else if ((message.GetPlayerId() == auction->GetCreatorId()) &&
			  !auction->IsActive())
	{
		OnCancelAuction(message.GetTrackId(), ARC_AuctionAlreadyCompleted,
			message.GetResponseId(), message.GetAuctionId(),
			message.GetPlayerId(), zeroNetworkId, 0,
			auction->GetLocation().GetLocationString());
		return;
	}

	auction->Expire(false, false, message.GetTrackId());

	const AuctionBid *highBid = auction->GetHighBid();
	NetworkId highBidderId = zeroNetworkId;
	int highBidAmount = 0;
	if (highBid)
	{
		highBidderId = highBid->GetBidderId();
		highBidAmount = highBid->GetMaxProxyBid();
	}

	OnCancelAuction(message.GetTrackId(), ARC_Success,
		message.GetResponseId(), message.GetAuctionId(),
		message.GetPlayerId(), highBidderId, highBidAmount,
		auction->GetLocation().GetLocationString());
}

// ----------------------------------------------------------------------

void AuctionMarket::AcceptHighBid(const AcceptHighBidMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : TrackId : %d.\n", message.GetTrackId()));

	Auction *auction = nullptr;
	AuctionResultCode result = ARC_Success;
	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(
		message.GetAuctionId());
	if (iter == m_auctions.end())
	{
		result = ARC_AuctionDoesNotExist;
	}
	else
	{
		auction = (*iter).second;
		if (message.GetPlayerId() != auction->GetCreatorId())
		{
			result = ARC_NotItemOwner;
		}
		else if (auction->GetHighBid() == nullptr)
		{
			result = ARC_NoBids;
		}
		else if (!auction->IsActive())
		{
			result = ARC_AuctionAlreadyCompleted;
		}
	}

	if (result == ARC_Success)
	{
		auction->Expire(true, false, message.GetTrackId());
	}

	OnAcceptHighBid(message.GetTrackId(), result,
		message.GetResponseId(), message.GetAuctionId(),
		message.GetPlayerId());

}

// ----------------------------------------------------------------------

void AuctionMarket::QueryAuctionHeaders(
	const QueryAuctionHeadersMessage &message
)
{
	// Break the text filter string for matching ALL tokens into lower-case tokens
	Unicode::UnicodeStringVector textFilterAllTokens;
	IGNORE_RETURN(Unicode::tokenize(Unicode::toLower(message.GetTextFilterAll()), textFilterAllTokens));

	// Break the text filter string for matching ANY tokens into lower-case tokens
	Unicode::UnicodeStringVector textFilterAnyTokens;
	IGNORE_RETURN(Unicode::tokenize(Unicode::toLower(message.GetTextFilterAny()), textFilterAnyTokens));

	std::string debugOutput;

#ifdef _DEBUG
	if (m_showAllDebugInfo || message.GetOverrideVendorSearchFlag())
#else
	if (message.GetOverrideVendorSearchFlag())
#endif
	{
		debugOutput = "Commodities Server QueryAuctionHeadersMessage:\r\n";

		char buffer[4096];

		snprintf(buffer, sizeof(buffer)-1, "ResponseId = (%d)", message.GetResponseId());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "TrackId = (%d)", message.GetTrackId());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "PlayerId = (%s)", message.GetPlayerId().getValueString().c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "VendorId = (%s)", message.GetVendorId().getValueString().c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		if (message.GetQueryType() == AST_ByCategory)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByCategory)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByLocation)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByLocation)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByAll)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByAll)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByPlayerSales)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerSales)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByPlayerBids)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerBids)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByPlayerStockroom)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerStockroom)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByVendorOffers)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorOffers)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByVendorSelling)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorSelling)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByVendorStockroom)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorStockroom)", message.GetQueryType());
		}
		else if (message.GetQueryType() == AST_ByPlayerOffersToVendor)
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerOffersToVendor)", message.GetQueryType());
		}
		else
		{
			snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d)", message.GetQueryType());
		}

		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "ItemType = (%d, %s)", message.GetItemType(), GameObjectTypes::getCanonicalName(message.GetItemType()).c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "ItemTypeExactMatch = (%s)", (message.GetItemTypeExactMatch() ? "yes" : "no"));
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "ItemTemplate = (%d)", message.GetItemTemplateId());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "TextFilterAll = (%s)", Unicode::wideToNarrow(message.GetTextFilterAll()).c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		for (Unicode::UnicodeStringVector::const_iterator iterTextFilterAllTokens = textFilterAllTokens.begin(); iterTextFilterAllTokens != textFilterAllTokens.end(); ++iterTextFilterAllTokens)
		{
			snprintf(buffer, sizeof(buffer)-1, "TextFilterAll = (%s)", Unicode::wideToNarrow(*iterTextFilterAllTokens).c_str());
			buffer[sizeof(buffer)-1] = '\0';
			debugOutput += buffer;
			debugOutput += "\r\n";
#ifdef _DEBUG
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif
		}

		snprintf(buffer, sizeof(buffer)-1, "TextFilterAny = (%s)", Unicode::wideToNarrow(message.GetTextFilterAny()).c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		for (Unicode::UnicodeStringVector::const_iterator iterTextFilterAnyTokens = textFilterAnyTokens.begin(); iterTextFilterAnyTokens != textFilterAnyTokens.end(); ++iterTextFilterAnyTokens)
		{
			snprintf(buffer, sizeof(buffer)-1, "TextFilterAny = (%s)", Unicode::wideToNarrow(*iterTextFilterAnyTokens).c_str());
			buffer[sizeof(buffer)-1] = '\0';
			debugOutput += buffer;
			debugOutput += "\r\n";
#ifdef _DEBUG
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif
		}

		snprintf(buffer, sizeof(buffer)-1, "MinPrice = (%d)", message.GetPriceFilterMin());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "MaxPrice = (%d)", message.GetPriceFilterMax());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "PriceIncludesEntranceFee = (%s)", (message.GetPriceFilterIncludesFee() ? "yes" : "no"));
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "LocationPlanet = (%s)", message.GetSearchStringPlanet().c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "LocationRegion = (%s)", message.GetSearchStringRegion().c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "LocationAuctionLocationId = (%s)", message.GetSearchAuctionLocationId().getValueString().c_str());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "SearchMyVendorsOnly = (%s)", (message.GetSearchMyVendorsOnly() ? "yes" : "no"));
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "OverrideVendorSearchFlag = (%s)", (message.GetOverrideVendorSearchFlag() ? "yes" : "no"));
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		snprintf(buffer, sizeof(buffer)-1, "QueryOffset = (%u)", message.GetQueryOffset());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		if (!message.getAdvancedSearch().empty())
		{
			if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_match_all)
			{
				snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_match_all");
			}
			else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_match_any)
			{
				snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_match_any");
			}
			else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_not_match_all)
			{
				snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_not_match_all");
			}
			else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_not_match_any)
			{
				snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_not_match_any");
			}
			else
			{
				snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = UNKNOWN (%d)", static_cast<int>(message.getAdvancedSearchMatchAllAny()));
			}

			buffer[sizeof(buffer)-1] = '\0';
			debugOutput += buffer;
			debugOutput += "\r\n";
#ifdef _DEBUG
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

			std::map<std::string, CommoditiesAdvancedSearchAttribute::SearchAttribute const *> const & sa = CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(message.GetItemType());
			std::string attributeName;

			for (std::list<AuctionQueryHeadersMessage::SearchCondition>::const_iterator iter = message.getAdvancedSearch().begin(); iter != message.getAdvancedSearch().end(); ++iter)
			{
				attributeName.clear();
				if (!sa.empty())
				{
					for (std::map<std::string, CommoditiesAdvancedSearchAttribute::SearchAttribute const *>::const_iterator iterSa = sa.begin(); iterSa != sa.end(); ++iterSa)
					{
						if (iterSa->second->attributeNameCrc == iter->attributeNameCrc)
						{
							attributeName = iterSa->second->attributeName;
							break;
						}
					}
				}

				if (iter->comparison == AuctionQueryHeadersMessage::SCC_int)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_int (%d, %d) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->intMin, iter->intMax, (iter->requiredAttribute ? "yes" : "no"));
				}
				else if (iter->comparison == AuctionQueryHeadersMessage::SCC_float)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_float (%.2f, %.2f) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->floatMin, iter->floatMax, (iter->requiredAttribute ? "yes" : "no"));
				}
				else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_equal)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_equal (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no"));
				}
				else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_not_equal)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_not_equal (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no"));
				}
				else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_contain)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_contain (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no"));
				}
				else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_not_contain)
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_not_contain (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no"));
				}
				else
				{
					snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) UNKNOWN COMPARISON (%d) (%d, %d) (%.2f, %.2f) (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, static_cast<int>(iter->comparison), iter->intMin, iter->intMax, iter->floatMin, iter->floatMax, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no"));
				}

				buffer[sizeof(buffer)-1] = '\0';
				debugOutput += buffer;
				debugOutput += "\r\n";
#ifdef _DEBUG
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif
			}
		}
		else
		{
			snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (none)");
			buffer[sizeof(buffer)-1] = '\0';
			debugOutput += buffer;
			debugOutput += "\r\n";
#ifdef _DEBUG
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif
		}
	}

	// The item template we are looking for
	int const itemTemplateId = message.GetItemTemplateId();

	// The item category we are looking for
	int const itemCategory = message.GetItemType();
	bool const itemCategoryMatchExact = (message.GetItemTypeExactMatch() && (itemCategory != 0) && !GameObjectTypes::isSubType(itemCategory) && (itemTemplateId == 0));

	// the combination of values of itemCategory and
	// itemTemplateId indicate what type of a search it is
	//
	// if itemCategory is 0xffffffff, then it is a search
	// for a resource container with a specific name.
	// itemTemplateId contains the crc value of the resource name
	//
	// else if itemCategory is GOT type GOT_resource_container
	// and itemTemplateId is != 0, then it is a search
	// for a resource container of a particular resource
	// class (or derives from the particular resource class).
	// itemTemplateId contains the crc value
	// of the name of the resource class
	//
	// else if itemTemplateId is == 0, then it is a
	// search for items belonging to the GOT type specified
	// by itemCategory
	//
	// else if itemTemplateId is != 0, then it is a
	// search for a specific item type. itemCategory
	// specifies the GOT and itemTemplateId is the
	// crc value of the object template

	// The min and max price of the items we are looking for
	int const priceFilterMin = message.GetPriceFilterMin();
	int const priceFilterMax = message.GetPriceFilterMax();

	// Advanced "attribute value" search
	std::list<AuctionQueryHeadersMessage::SearchCondition> const & advancedSearch = message.getAdvancedSearch();
	bool const useAdvancedSearch = !advancedSearch.empty();

	// For the price filter, do we want to include the entrance fee?
	bool const priceFilterIncludesFee = message.GetPriceFilterIncludesFee();

	// Indicates searching for resource containers
	bool const searchForResourceContainer = (itemCategory != 0) && ((static_cast<unsigned int>(itemCategory) == 0xffffffff) || (AuctionItem::IsCategoryResourceContainer(itemCategory)));

	bool hasMorePages = false;
	uint queryOffset = message.GetQueryOffset();
	uint numOffset = 0;
	int numAuctions = 0;
	std::vector<AuctionDataHeader> headers;

	bool allowSearchVendors = true;

	if (message.GetQueryType() != AST_ByPlayerOffersToVendor &&
		message.GetQueryType() != AST_ByVendorSelling        &&
		message.GetQueryType() != AST_ByPlayerStockroom      &&
		message.GetQueryType() != AST_ByVendorOffers         &&
		message.GetQueryType() != AST_ByVendorStockroom)
	{
		allowSearchVendors = false;
	}

	bool checkLocationInfo = false;
	static std::map<NetworkId, AuctionLocation *> emptyAuctionLocationList;
	std::map<NetworkId, AuctionLocation *>::iterator locationIter = emptyAuctionLocationList.begin();;
	std::map<NetworkId, AuctionLocation *>::iterator locationIterEnd = emptyAuctionLocationList.end();

	// specific vendor is specified
	// covers all cases of a non vendor owner accessing a vendor and all cases
	// where "this vendor" radio button is selected from the location filter
	if (message.GetSearchAuctionLocationId().isValid())
	{
		locationIter = m_locationIdMap.find(message.GetSearchAuctionLocationId());
		locationIterEnd = locationIter;

		if (locationIterEnd != m_locationIdMap.end())
		{
			++locationIterEnd;
		}
	}
	// only search vendors owned by the player
	// covers all cases of a vendor owner accessing a vendor he owns
	else if (message.GetSearchMyVendorsOnly())
	{
		checkLocationInfo = true;
		std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_playerVendorListMap.find(message.GetPlayerId());
		if (iterFind != m_playerVendorListMap.end())
		{
			locationIter = iterFind->second.begin();
			locationIterEnd = iterFind->second.end();
		}
	}
	// the rest of the cases just need to cover the various cases of browsing the bazaar
	// bazaar "all auctions"
	else if (message.GetQueryType() == AST_ByAll)
	{
		if (message.GetSearchStringPlanet().empty())
		{
			locationIter = m_allBazaar.begin();
			locationIterEnd =  m_allBazaar.end();
		}
		else if (message.GetSearchStringRegion().empty())
		{
			std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_bazaarByPlanet.find(message.GetSearchStringPlanet());
			if (iterFind != m_bazaarByPlanet.end())
			{
				locationIter = iterFind->second.begin();
				locationIterEnd = iterFind->second.end();
			}
		}
		else
		{
			std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_bazaarByRegion.find(std::make_pair(message.GetSearchStringPlanet(), message.GetSearchStringRegion()));
			if (iterFind != m_bazaarByRegion.end())
			{
				locationIter = iterFind->second.begin();
				locationIterEnd = iterFind->second.end();
			}
		}
	}
	// bazaar "my bids" and "my sales"
	else if ((message.GetQueryType() == AST_ByPlayerBids) || (message.GetQueryType() == AST_ByPlayerSales))
	{
		locationIter = m_allBazaar.begin();
		locationIterEnd =  m_allBazaar.end();
	}
	// bazaar "available items"
	else if (message.GetQueryType() == AST_ByPlayerStockroom)
	{
		locationIter = m_locationIdMap.begin();
		locationIterEnd = m_locationIdMap.end();
	}
	// bazaar "vendor location"
	else if (message.GetQueryType() == AST_ByVendorSelling)
	{
		if (message.GetOverrideVendorSearchFlag())
		{
			checkLocationInfo = true;
			locationIter = m_locationIdMap.begin();
			locationIterEnd = m_locationIdMap.end();
		}
		else if (message.GetSearchStringPlanet().empty())
		{
			locationIter = m_allSearchableVendor.begin();
			locationIterEnd = m_allSearchableVendor.end();
		}
		else if (message.GetSearchStringRegion().empty())
		{
			std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_searchableVendorByPlanet.find(message.GetSearchStringPlanet());
			if (iterFind != m_searchableVendorByPlanet.end())
			{
				locationIter = iterFind->second.begin();
				locationIterEnd = iterFind->second.end();
			}
		}
		else
		{
			std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_searchableVendorByRegion.find(std::make_pair(message.GetSearchStringPlanet(), message.GetSearchStringRegion()));
			if (iterFind != m_searchableVendorByRegion.end())
			{
				locationIter = iterFind->second.begin();
				locationIterEnd = iterFind->second.end();
			}
		}
	}

	int debugNumberLocationsTested = 0;
	int debugNumberLocationsMatched = 0;
	int debugNumberAuctionsTested = 0;

	std::map<NetworkId, Auction *> *auctionsPtr = nullptr;
	int entranceCharge = 0;
	AuctionLocation *locationPtr = nullptr;
	Auction *auctionPtr = nullptr;
	std::map<NetworkId, Auction *>::const_iterator auctionIterator;
	AuctionDataHeader *header = nullptr;
	bool checkItemTemplate;
	while (locationIter != locationIterEnd)
	{
		++debugNumberLocationsTested;

		checkItemTemplate = false;
		auctionsPtr = nullptr;
		entranceCharge = 0;
		locationPtr = (*locationIter).second;

		if (locationPtr->MatchLocation(message.GetSearchStringPlanet(), message.GetSearchStringRegion(), message.GetSearchAuctionLocationId(), checkLocationInfo, message.GetSearchMyVendorsOnly(), message.GetOverrideVendorSearchFlag(), message.GetPlayerId(), allowSearchVendors, message.GetVendorId(), message.GetQueryType()))
		{
			++debugNumberLocationsMatched;

			entranceCharge = locationPtr->GetEntranceCharge();

			if (message.GetQueryType() == AST_ByVendorOffers ||
				message.GetQueryType() == AST_ByPlayerOffersToVendor ||
				message.GetQueryType() == AST_ByVendorStockroom ||
				(message.GetQueryType() == AST_ByPlayerStockroom &&
				 locationPtr->IsVendorMarket()))
			{
				// we are using a list of all items, so we will need to check
				// to see if the player specified a template and/or item type,
				// and if so, ignore any items that doesn't match the template
				// and/or item type
				//
				// in all other cases, we use the template and/or item type
				// that the player specified, and only look at the item list
				// of that particular template and/or item type, so we know that
				// every item in that list matches the specified template and/or
				// item type
				checkItemTemplate = true;

				auctionsPtr = &(locationPtr->GetVendorOffers());
			}
			else
			{
				if (searchForResourceContainer)
				{
					auctionsPtr = &(locationPtr->GetAuctionsResourceContainer());
				}
				else if (itemCategory != 0)
				{
					if (itemTemplateId == 0)
					{
						if (itemCategoryMatchExact)
						{
							auctionsPtr = &(locationPtr->GetAuctionsByParentTypeExactMatch(itemCategory));
						}
						else
						{
							auctionsPtr = &(locationPtr->GetAuctionsByType(itemCategory));
						}
					}
					else
					{
						auctionsPtr = &(locationPtr->GetAuctionsByTemplate(itemCategory, itemTemplateId));
					}
				}
				else
				{
					auctionsPtr = &(locationPtr->GetAuctions());
				}
			}
		}

		if (auctionsPtr)
		{
			for (auctionIterator = auctionsPtr->begin(); auctionIterator != auctionsPtr->end(); ++auctionIterator)
			{
				++debugNumberAuctionsTested;

				auctionPtr = (*auctionIterator).second;
				const AuctionItem &item = auctionPtr->GetItem();
				header = nullptr;

				// Check to see if the item template matches
				if (searchForResourceContainer && (itemTemplateId != 0))
				{
					if (checkItemTemplate && !AuctionItem::IsCategoryResourceContainer(item.GetCategory()))
					{
						continue;
					}

					if (static_cast<unsigned int>(itemCategory) == 0xffffffff)
					{
						if (item.GetResourceNameCrc() != itemTemplateId)
						{
							continue;
						}
					}
					else if (!IsResourceClassDerivedFrom(item.GetResourceContainerClassCrc(), itemTemplateId))
					{
						continue;
					}
				}
				else if (checkItemTemplate && (itemCategory != 0))
				{
					if (itemCategoryMatchExact)
					{
						if (itemCategory != item.GetCategory())
						{
							continue;
						}
					}
					else if (!GameObjectTypes::isTypeOf(item.GetCategory(), itemCategory))
					{
						continue;
					}

					if ((itemTemplateId != 0) && (itemTemplateId != item.GetItemTemplateId()))
					{
						continue;
					}
				}

				// Check to see if the text matches
				if (!((textFilterAllTokens.empty() && textFilterAnyTokens.empty()) ||
					IsTextFilterMatch(item.GetName(), textFilterAllTokens, textFilterAnyTokens)))
				{
					continue;
				}

				// Check to see if the price matches
				if (!(((priceFilterMin == 0) && (priceFilterMax == 0)) ||
					IsPriceFilterMatch(auctionPtr, entranceCharge, priceFilterMin, priceFilterMax, priceFilterIncludesFee)))
				{
					continue;
				}

				// Check to see if the advanced search matches
				if (!(!useAdvancedSearch || auctionPtr->IsAdvancedFilterMatch(advancedSearch, static_cast<int>(message.getAdvancedSearchMatchAllAny()))))
				{
					continue;
				}

				switch(message.GetQueryType())
				{
					case AST_ByLocation:
					case AST_ByAll:
					case AST_ByVendorOffers:
					case AST_ByVendorSelling:
						if (auctionPtr->IsActive())
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge);
							}
							else
							{
								++numOffset;
							}
						}
						break;

					case AST_ByPlayerSales:
						if (auctionPtr->IsActive() &&
						    auctionPtr->GetCreatorId() == message.GetPlayerId())
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge);
							}
							else
							{
								++numOffset;
							}
						}
						break;

					case AST_ByPlayerStockroom:
					case AST_ByVendorStockroom:
						if (!auctionPtr->IsActive() &&
						    auctionPtr->GetItem().GetOwnerId() == message.GetPlayerId())
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge);
							}
							else
							{
								++numOffset;
							}
						}
						break;

					case AST_ByPlayerOffersToVendor:
						if (auctionPtr->IsActive() &&
						    auctionPtr->GetCreatorId() == message.GetPlayerId())
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge);
							}
							else
							{
								++numOffset;
							}
						}
						break;

					case AST_ByPlayerBids:
					{
						if (!auctionPtr->IsActive())
						{
							break;
						}
						const AuctionBid *bid = auctionPtr->GetPlayerBid(
							message.GetPlayerId());
						if (bid)
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge,
									bid);
							}
							else
							{
								++numOffset;
							}
						}
						break;
					}

					case AST_ByCategory:
						if (auctionPtr->IsActive())
						{
							if (numOffset >= queryOffset)
							{
								header = MakeDataHeader(
									message.GetPlayerId(), auctionPtr,
									static_cast<int>(message.GetQueryType()), entranceCharge);
							}
							else
							{
								++numOffset;
							}
						}
						break;
				}

				if (header)
				{
					headers.push_back(*header);
					delete header;

					++numAuctions;
					if (numAuctions >= ConfigCommodityServer::getMaxAuctionsPerPage())
					{
						hasMorePages = true;
						break;
					}
				}
			}
		}

		// If we found enough auctions, stop looking
		if (numAuctions >= ConfigCommodityServer::getMaxAuctionsPerPage())
		{
			break;
		}

		++locationIter;
	}

#ifdef _DEBUG
	if (m_showAllDebugInfo || message.GetOverrideVendorSearchFlag())
#else
	if (message.GetOverrideVendorSearchFlag())
#endif
	{
		char buffer[4096];

		snprintf(buffer, sizeof(buffer)-1, "(%d / %d / %d) locations tested, (%d / %d) auctions tested", debugNumberLocationsMatched, debugNumberLocationsTested, m_locationIdMap.size(), debugNumberAuctionsTested, m_auctions.size());
		buffer[sizeof(buffer)-1] = '\0';
		debugOutput += buffer;
		debugOutput += "\r\n";
#ifdef _DEBUG
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer));
#endif

		if (message.GetOverrideVendorSearchFlag())
		{
			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId());
			if (gameServerConn)
			{
				GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(message.GetPlayerId(), debugOutput));
				gameServerConn->send(msg, true);
			}
		}
	}

	OnQueryAuctionHeaders(message.GetTrackId(), ARC_Success,
		message.GetResponseId(), message.GetPlayerId(),
		message.GetQueryType(), headers, queryOffset, hasMorePages);
}

// ----------------------------------------------------------------------

void AuctionMarket::SetGameTime(const SetGameTimeMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : GameTime : %d.\n", message.GetGameTime()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : TrackId : %d.\n", message.GetTrackId()));

	m_gameTime = message.GetGameTime();
}

// ----------------------------------------------------------------------

void AuctionMarket::GetItemDetails(const GetItemDetailsMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(
		message.GetAuctionId());
	if (iter == m_auctions.end())
	{
		static const std::vector<std::pair<std::string, Unicode::String> > emptyAttributes;
		OnGetItemDetails(message.GetTrackId(), ARC_AuctionDoesNotExist,
			message.GetResponseId(), message.GetAuctionId(),
			message.GetPlayerId(), 0, Unicode::emptyString, 0, Unicode::emptyString, emptyAttributes);
		return;
	}

	Auction *auction = (*iter).second;
	OnGetItemDetails(message.GetTrackId(), ARC_Success,
					 message.GetResponseId(), message.GetAuctionId(),
					 message.GetPlayerId(),
					 auction->GetUserDescriptionLength(), auction->GetUserDescription(),
					 auction->GetOobLength(), auction->GetOobData(),
					 auction->GetAttributes());
}

// ----------------------------------------------------------------------

void AuctionMarket::GetItem(const GetItemMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : TrackId : %d.\n", message.GetTrackId()));

	AuctionLocation &location = GetLocation(std::string(message.GetLocation()));
	Auction *auction = location.GetAuction(message.GetItemId());
	if (!auction)
	{
		OnGetItem(message.GetTrackId(), ARC_AuctionDoesNotExist,
			message.GetResponseId(), message.GetItemId(),
			message.GetPlayerId(), message.GetLocation());
		return;
	}
	if (auction->GetItem().GetOwnerId() != message.GetPlayerId())
	{
		OnGetItem(message.GetTrackId(), ARC_NotItemOwner,
			message.GetResponseId(), message.GetItemId(),
			message.GetPlayerId(), message.GetLocation());
		return;
	}

	LOG("CommoditiesServer", ("Player %s retrived item %s at location %s",
		auction->GetItem().GetOwnerId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str()));
	LOG("CustomerService", ("Auction: Player %s retrived item %s at location %s",
		auction->GetItem().GetOwnerId().getValueString().c_str(),
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str()));
	std::map<NetworkId, Auction *>::iterator i = m_auctions.find(auction->GetItem().GetItemId());
	if (i != m_auctions.end())
	{
		LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because item is being retrieved.", (*i).second->GetItem().GetItemId().getValueString().c_str()));
		LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because item is being retrieved.", (*i).second->GetItem().GetItemId().getValueString().c_str()));
		DestroyAuction(i);
	}

	OnGetItem(message.GetTrackId(), ARC_Success,
		message.GetResponseId(), message.GetItemId(),
		message.GetPlayerId(), message.GetLocation());
}

// ----------------------------------------------------------------------

void AuctionMarket::CleanupInvalidItemRetrieval( const CleanupInvalidItemRetrievalMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : TrackId : %d.\n", message.GetTrackId()));

	//printf( "Received command to cleanup an invalid item.\n");
        std::map<NetworkId, Auction *>::iterator itemIterator = m_auctions.find( message.GetItemId());
	if( itemIterator != m_auctions.end() )
	{
		LOG("CommoditiesServer", ("CleanupInvalidItemRetrieval for item %s.",
			message.GetItemId().getValueString().c_str()));
		LOG("CustomerService", ("Auction: CleanupInvalidItemRetrieval for item %s.",
			message.GetItemId().getValueString().c_str()));
		int reimburseAmt = 0;
		Auction *item = (*itemIterator).second;
		if( item->GetCreatorId() != item->GetItem().GetOwnerId() )
		{
			//printf("Player needs reimbursed for item = %d.\n", item->GetItem().GetItemId() );

			// figure out the price.
			// For instant sales, the buy now price
			if( item->IsImmediate() )
			{
				reimburseAmt = item->GetBuyNowPriceWithSalesTax();
				//printf( "Reimbursing player %d credits for invalid instant auction.\n", reimburseAmt );
			}
			else
			{
				reimburseAmt = item->GetHighBid()->GetBid();
				//printf( "Reimbursing player %d credits for invalid bid auction.\n", reimburseAmt );
			}
			// For bid items, the highest bid
		}
		OnCleanupInvalidItemRetrieval(message.GetTrackId(), message.GetResponseId(), item->GetItem().GetItemId(), item->GetItem().GetOwnerId(), item->GetCreatorId(), reimburseAmt);
		LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because of cleanup of invalied item retieval.", (*itemIterator).second->GetItem().GetItemId().getValueString().c_str()));
		LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because of cleanup of invalied item retieval.", (*itemIterator).second->GetItem().GetItemId().getValueString().c_str()));

		//printf( "Deleting auction item = %d\n", item->GetItem().GetItemId() );
		DestroyAuction(itemIterator);
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::DestroyVendorMarket(const DestroyVendorMarketMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, AuctionLocation *>::iterator i = m_locationIdMap.find(GetLocationId(message.GetLocation()));
	if( i != m_locationIdMap.end() )
	{
		LOG("CommoditiesServer", ("Remove location %s owned by %s (%s) from Commodities Server",
			GetLocationId(message.GetLocation()).getValueString().c_str(),
			message.GetOwnerName().c_str(),
			message.GetOwnerId().getValueString().c_str()));
		LOG("CustomerService", ("Vendor: Remove location %s owned by %s (%s) from Commodities Server",
			GetLocationId(message.GetLocation()).getValueString().c_str(),
			message.GetOwnerName().c_str(),
			message.GetOwnerId().getValueString().c_str()));
		std::vector<std::map<NetworkId, Auction *>::iterator> destroyedAuctions;
		std::map<NetworkId, Auction *>::iterator item;
		// get all the auctions for this location and get an iterator from the real auctions map
		for( std::map<NetworkId, Auction*>::iterator j = (*i).second->GetAuctions().begin(); j != (*i).second->GetAuctions().end(); j++ )
		{
			item = m_auctions.find((*j).first);
			if( item != m_auctions.end() )
			{
				destroyedAuctions.push_back(item);
			}
		}

		// do it again for all vendor offers
		for( std::map<NetworkId, Auction*>::iterator k = (*i).second->GetVendorOffers().begin(); k != (*i).second->GetVendorOffers().end(); k++ )
		{
			item = m_auctions.find((*k).first);
			if( item != m_auctions.end() )
			{
				destroyedAuctions.push_back(item);
			}
		}


		// destroy the auctions
		std::vector<std::map<NetworkId, Auction *>::iterator>::iterator ri = destroyedAuctions.begin();
		std::map<NetworkId, Auction *>::iterator auctionsIterator;
		while (ri != destroyedAuctions.end())
		{
			auctionsIterator = *ri;
			//(*auctionsIterator).second->Expire(false, false);
			LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because vendor is being destroyed by the owner.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str()));
			LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because vendor is being destroyed by the owner.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str()));
			DestroyAuction(auctionsIterator);
			++ri;
		}

		// get rid of the location from m_locationMap
		AuctionLocation *al = (*i).second;
		if (al->GetOwnerId() != zeroNetworkId)
		{
			RemovePlayerVendor(al->GetOwnerId(), al->GetLocationId());
		}
		m_locationIdMap.erase(i);

		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteLocationMessage.\n"));

		CMDeleteLocationMessage msg(al->GetLocationId());
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str()));

		DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
		if (dbServer)
			dbServer->send(msg, true);

		delete al;
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::DeleteAuctionLocation(const DeleteAuctionLocationMessage &message)
{
	std::string replyMessage;

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DeleteAuctionLocationMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str()));

	std::map<NetworkId, AuctionLocation *>::iterator i = m_locationIdMap.find(message.GetLocationId());
	if( i != m_locationIdMap.end() )
	{
		LOG("CommoditiesServer", ("Remove location %s owned by %s from Commodities Server",
			message.GetLocationId().getValueString().c_str(),
			(*i).second->GetOwnerId().getValueString().c_str()));

		LOG("CustomerService", ("Vendor: Remove location %s owned by %s from Commodities Server",
			message.GetLocationId().getValueString().c_str(),
			(*i).second->GetOwnerId().getValueString().c_str()));
		std::vector<std::map<NetworkId, Auction *>::iterator> destroyedAuctions;
		std::map<NetworkId, Auction *>::iterator item;
		// get all the auctions for this location and get an iterator from the real auctions map
		for( std::map<NetworkId, Auction*>::iterator j = (*i).second->GetAuctions().begin(); j != (*i).second->GetAuctions().end(); j++ )
		{
			item = m_auctions.find((*j).first);
			if( item != m_auctions.end() )
			{
				destroyedAuctions.push_back(item);
			}
		}

		// do it again for all vendor offers
		for( std::map<NetworkId, Auction*>::iterator k = (*i).second->GetVendorOffers().begin(); k != (*i).second->GetVendorOffers().end(); k++ )
		{
			item = m_auctions.find((*k).first);
			if( item != m_auctions.end() )
			{
				destroyedAuctions.push_back(item);
			}
		}


		// destroy the auctions
		std::vector<std::map<NetworkId, Auction *>::iterator>::iterator ri = destroyedAuctions.begin();
		std::map<NetworkId, Auction *>::iterator auctionsIterator;
		while (ri != destroyedAuctions.end())
		{
			auctionsIterator = *ri;
			//(*auctionsIterator).second->Expire(false, false);
			LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction location is being deleted from DeleteAuctionLocationMessage request.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str()));
			LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction location is being deleted from DeleteAuctionLocationMessage request.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str()));
			DestroyAuction(auctionsIterator);
			++ri;
		}

		// get rid of the location from m_locationMap
		AuctionLocation *al = (*i).second;
		if (al->GetOwnerId() != zeroNetworkId)
		{
			RemovePlayerVendor(al->GetOwnerId(), al->GetLocationId());
		}
		m_locationIdMap.erase(i);

		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteLocationMessage.\n"));

		replyMessage = std::string("Location ") + message.GetLocationId().getValueString().c_str() + " owned by " + al->GetOwnerId().getValueString().c_str() + " is deleted.";
		CMDeleteLocationMessage msg(al->GetLocationId());
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str()));

		DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
		if (dbServer)
			dbServer->send(msg, true);

		delete al;
	}
	else
		replyMessage = std::string("Location ") + message.GetLocationId().getValueString().c_str() + " does not exist.";

	GenericValueTypeMessage<std::pair<std::string, std::string> >
		reply("OnCommodityReplyMessage",
		std::make_pair(message.GetWhoRequested(), replyMessage));
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId());
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCommodityReplyMessage callback to GamerServer ID: %d.\n", message.GetTrackId()));
		gameServerConn->send(reply, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", message.GetTrackId()));
	}

}

// ----------------------------------------------------------------------

void AuctionMarket::UpdateVendorStatus(const UpdateVendorStatusMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : VendorId : %s.\n", message.GetVendorId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Status : 0x%0X.\n", message.GetStatus()));

	std::map<NetworkId, AuctionLocation *>::const_iterator i = m_locationIdMap.find(GetLocationId(message.GetLocation()));

	if (i != m_locationIdMap.end())
	{
		(*i).second->SetLocationString(message.GetLocation());
		(*i).second->SetFullStatus(message.GetStatus(), true);

		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : LocationId : %s.\n", (*i).second->GetLocationId().getValueString().c_str()));
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Full Status : 0x%0X.\n", (*i).second->GetFullStatus()));

		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n"));
		CMUpdateLocationMessage msg(
			(*i).second->GetLocationId(),
			(*i).second->GetOwnerId(),
			(*i).second->GetLocationString(),
			(*i).second->GetSalesTax(),
			(*i).second->GetSalesTaxBankId(),
			(*i).second->GetEmptyDate(),
			(*i).second->GetLastAccessDate(),
			(*i).second->GetInactiveDate(),
			(*i).second->GetFullStatus(),
			(*i).second->GetSearchEnabled(),
			(*i).second->GetEntranceCharge()
			);

		DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
		if (dbServer)
			dbServer->send(msg, true);
	}
	else
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Update failed - Vendor not found!\n"));
}

// ----------------------------------------------------------------------

void AuctionMarket::UpdateVendorLocation(const NetworkId &locationId, const std::string &locationString)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : VendorId : %s.\n", locationId.getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : Location : %s.\n", locationString.c_str()));

	std::map<NetworkId, AuctionLocation *>::const_iterator i = m_locationIdMap.find(locationId);

	if (i != m_locationIdMap.end())
	{
		if  ((*i).second->GetLocationString() != locationString)
		{
			LOG("CustomerService", ("Vendor: Fixing up vendor %s (owner %s) location from (%s) to (%s)", (*i).second->GetLocationId().getValueString().c_str(), (*i).second->GetOwnerId().getValueString().c_str(), (*i).second->GetLocationString().c_str(), locationString.c_str()));

			(*i).second->SetLocationString(locationString);

			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n"));
			CMUpdateLocationMessage msg(
				(*i).second->GetLocationId(),
				(*i).second->GetOwnerId(),
				(*i).second->GetLocationString(),
				(*i).second->GetSalesTax(),
				(*i).second->GetSalesTaxBankId(),
				(*i).second->GetEmptyDate(),
				(*i).second->GetLastAccessDate(),
				(*i).second->GetInactiveDate(),
				(*i).second->GetFullStatus(),
				(*i).second->GetSearchEnabled(),
				(*i).second->GetEntranceCharge()
				);

			DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
			if (dbServer)
				dbServer->send(msg, true);
		}
	}
	else
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : Update failed - Vendor not found!\n"));
}

// ----------------------------------------------------------------------

void AuctionMarket::CreateVendorMarket(const CreateVendorMarketMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit : %d.\n", message.GetVendorLimit()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Entrance Charge : %d.\n", message.GetEntranceCharge()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, AuctionLocation *>::const_iterator i =
		m_locationIdMap.find(GetLocationId(message.GetLocation()));
	if (i != m_locationIdMap.end())
	{
		// check the current owner and location string - update if needed
		if (((*i).second->GetOwnerId() != message.GetOwnerId()) || ((*i).second->GetLocationString() != message.GetLocation()))
		{
			// check the player's vendor limit
			if (GetVendorCount(message.GetOwnerId()) >= message.GetVendorLimit())
			{
				OnCreateVendorMarket(message.GetTrackId(),
					ARC_LocationVendorLimitExceeded,
					message.GetResponseId(),
					message.GetOwnerId(),
					message.GetLocation());
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit()));
				return;
			}

			RemovePlayerVendor((*i).second->GetOwnerId(), (*i).second->GetLocationId());
			AddPlayerVendor(message.GetOwnerId(), (*i).second->GetLocationId(), (*i).second);
			(*i).second->SetOwnerId(message.GetOwnerId());
			(*i).second->SetLocationString(message.GetLocation());
			(*i).second->SetEntranceCharge(message.GetEntranceCharge());
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n"));
			CMUpdateLocationMessage msg(
				(*i).second->GetLocationId(),
				(*i).second->GetOwnerId(),
				(*i).second->GetLocationString(),
				(*i).second->GetSalesTax(),
				(*i).second->GetSalesTaxBankId(),
				(*i).second->GetEmptyDate(),
				(*i).second->GetLastAccessDate(),
				(*i).second->GetInactiveDate(),
				(*i).second->GetFullStatus(),
				(*i).second->GetSearchEnabled(),
				(*i).second->GetEntranceCharge()
			);
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location OwnerId : %s.\n", msg.GetOwnerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str()));

			DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
			if (dbServer)
				dbServer->send(msg, true);
		}
		// This should only be for the reinitialize case
		else if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit())
		{
			OnCreateVendorMarket(message.GetTrackId(),
				ARC_LocationVendorLimitExceeded,
				message.GetResponseId(),
				message.GetOwnerId(),
				message.GetLocation());
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit()));
			return;
		}

		OnCreateVendorMarket(message.GetTrackId(),
			ARC_LocationAlreadyExists,
			message.GetResponseId(),
			message.GetOwnerId(),
			message.GetLocation());
			return;
	}

	// check the player's vendor limit
	if (GetVendorCount(message.GetOwnerId()) >= message.GetVendorLimit())
	{
		OnCreateVendorMarket(message.GetTrackId(),
			ARC_LocationVendorLimitExceeded,
			message.GetResponseId(),
			message.GetOwnerId(),
			message.GetLocation());
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit()));
		return;
	}

	CreateLocation(message.GetOwnerId(), message.GetLocation(), message.GetEntranceCharge());

	OnCreateVendorMarket(message.GetTrackId(),
		ARC_Success,
		message.GetResponseId(),
		message.GetOwnerId(),
		message.GetLocation());
}

// ----------------------------------------------------------------------

// returns the containerId as a string given a location string
bool AuctionMarket::GetContainerIdString( const std::string &loc, std::string &output )
{
	// format of location string is as follows:
	// planetname.regionname.vendorname.containerId#xLoc,zLoc
	const std::string delims1(".");
	const std::string delims2("#");
	bool retval = false;

	std::string::size_type begIdx, endIdx;

	begIdx = loc.find_first_not_of(delims1);
	// skip over first 3 '.'s
	for( int i=0; i<3; i++ )
	{
		begIdx = loc.find_first_of(delims1, begIdx);
		if( begIdx != std::string::npos )
		{
			begIdx = loc.find_first_not_of(delims1, begIdx);
		}
	}

	if( begIdx != std::string::npos )
	{
		endIdx = loc.find_first_of(delims2, begIdx);
		if( endIdx != std::string::npos )
		{
			output = loc.substr(begIdx, endIdx-begIdx);
			retval =  true;
		}
	}

	return retval;
}

// ----------------------------------------------------------------------

// returns the locationId as a number given a location string
NetworkId AuctionMarket::GetLocationId(const std::string &loc)
{
	// format of location string is as follows:
	// planetname.regionname.vendorname.containerId#xLoc,zLoc
	const std::string delims1(".");
	const std::string delims2("#");
	std::string output;
	bool found = false;

	std::string::size_type begIdx, endIdx;

	begIdx = loc.find_first_not_of(delims1);
	// skip over first 3 '.'s
	for( int i=0; i<3; i++ )
	{
		begIdx = loc.find_first_of(delims1, begIdx);
		if( begIdx != std::string::npos )
		{
			begIdx = loc.find_first_not_of(delims1, begIdx);
		}
	}

	if( begIdx != std::string::npos )
	{
		endIdx = loc.find_first_of(delims2, begIdx);
		if( endIdx != std::string::npos )
		{
			output = loc.substr(begIdx, endIdx-begIdx);
			found = true;
		}
	}

	if (found)
	{
		NetworkId retval(output);
		return retval;
	}
	else
	{
		NetworkId retval(int64(0));
		return retval;
	}
}

// ----------------------------------------------------------------------

// This function checks to see if the embedded containerId matches with any existing
// vendor location string.  If it does, it updates the location string for that match
//
// returns true if it fixed something, false otherwise
bool AuctionMarket::FixVendorLocation( const std::string &loc )
{
	std::map<NetworkId, AuctionLocation *>::iterator i = m_locationIdMap.begin();

	std::string containerIdString;
	if( !GetContainerIdString(loc, containerIdString) )
	{
		return false;
	}

	while( i != m_locationIdMap.end() )
	{
		AuctionLocation *al = (*i).second;
		if( al )
		{
			std::string oldStrLoc(al->GetLocationString());
			//printf( "Old strloc: %s\n", oldStrLoc);
			std::string checkId;
			//printf( "checking %s with %s\n", checkId, containerIdString);

			if( GetContainerIdString( oldStrLoc, checkId ) && checkId == containerIdString )
			{
				// update the location string
				al->SetLocationString( loc );

				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n"));
				CMUpdateLocationMessage msg(
					al->GetLocationId(),
					al->GetOwnerId(),
					loc,
					al->GetSalesTax(),
					al->GetSalesTaxBankId(),
					al->GetEmptyDate(),
					al->GetLastAccessDate(),
					al->GetInactiveDate(),
					al->GetFullStatus(),
					al->GetSearchEnabled(),
					al->GetEntranceCharge()
				);
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str()));
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str()));
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Sales Tax : %d.\n", msg.GetSalesTax()));
				DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Bank Id : %s.\n", msg.GetBankId().getValueString().c_str()));

				DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
				if (dbServer)
					dbServer->send(msg, true);

				return true;
			}
		}

		i++;
	}

	return false;
}

// ----------------------------------------------------------------------

void AuctionMarket::GetVendorOwner(const GetVendorOwnerMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, AuctionLocation *>::const_iterator i =
		m_locationIdMap.find(GetLocationId(message.GetLocation()));
	if (i == m_locationIdMap.end())
	{
		// if the region name changes, we lose track of an existing vendor
		// this function will fix up those vendors.
		if( FixVendorLocation(message.GetLocation()) )
		{
			// try again now...
			i = m_locationIdMap.find(GetLocationId(message.GetLocation()));
			if( i == m_locationIdMap.end() )
			{
				// still couldn't find the vendor
				OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists,
					message.GetResponseId(), zeroNetworkId,
					message.GetOwnerId(), message.GetLocation());
				return;
			}
		}
		else
		{	// couldn't find the vendor
			OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists,
				message.GetResponseId(), zeroNetworkId,
				message.GetOwnerId(), message.GetLocation());
			return;
		}
	}
	AuctionLocation *auctionLocation = (*i).second;

	OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists,
		message.GetResponseId(), auctionLocation->GetOwnerId(),
		message.GetOwnerId(), message.GetLocation());
}

// ----------------------------------------------------------------------

void AuctionMarket::GetVendorValue(const GetVendorValueMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : TrackId : %d.\n", message.GetTrackId()));

	std::map<NetworkId, AuctionLocation *>::const_iterator i =
		m_locationIdMap.find(GetLocationId(message.GetLocation()));
	if (i == m_locationIdMap.end())
	{
		OnGetVendorValue(message.GetTrackId(), message.GetResponseId(),
			message.GetLocation(), 0);
		return;
	}
	AuctionLocation *auctionLocation = (*i).second;

	OnGetVendorValue(message.GetTrackId(), message.GetResponseId(),
		message.GetLocation(), auctionLocation->GetValue());
}

// ----------------------------------------------------------------------

void AuctionMarket::SetSalesTax(const SetSalesTaxMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : GetBankId : %s.\n", message.GetBankId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : GetSalesTax : %d.\n", message.GetSalesTax()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : Location : %s.\n", message.GetLocation().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : ResponseId : %d.\n", message.GetResponseId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : TrackId : %d.\n", message.GetTrackId()));

	// printf("Received SetSalesTax request: sales tax=%ld, bankId=%Ld, location='%s'\n", message.GetSalesTax(), message.GetBankId().getValue(), message.GetLocation() );

	AuctionLocation &al = GetLocation(message.GetLocation());
	// make sure we got a real location
	if( al.GetLocationString() == message.GetLocation() )
	{
		if ((al.GetSalesTax() != message.GetSalesTax()) || (al.GetSalesTaxBankId() != message.GetBankId()))
		{
			al.SetSalesTax(message.GetSalesTax(), message.GetBankId());
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n"));
			CMUpdateLocationMessage msg(
				al.GetLocationId(),
				al.GetOwnerId(),
				al.GetLocationString(),
				al.GetSalesTax(),
				al.GetSalesTaxBankId(),
				al.GetEmptyDate(),
				al.GetLastAccessDate(),
				al.GetInactiveDate(),
				al.GetFullStatus(),
				al.GetSearchEnabled(),
				al.GetEntranceCharge()
			);
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Sales Tax : %d.\n", msg.GetSalesTax()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Bank Id : %s.\n", msg.GetBankId().getValueString().c_str()));

			DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
			if (dbServer)
				dbServer->send(msg, true);
		}
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::QueryVendorItemCount(const QueryVendorItemCountMessage &message)
{
	AuctionLocation &loc = GetLocation(message.GetVendorId());
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : TrackId : %d\n", message.GetTrackId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : ItemCount : %d\n", loc.GetAuctionItemCount()));

	OnQueryVendorItemCount(message.GetResponseId(), message.GetTrackId(), message.GetVendorId(), loc.GetAuctionItemCount(), loc.GetSearchEnabled());
}

// ----------------------------------------------------------------------

void AuctionMarket::GetPlayerVendorCount(const GetPlayerVendorCountMessage &message)
{
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : TrackId : %d\n", message.GetTrackId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : VendorId : %s\n", message.GetPlayerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : ItemCount : %d\n", GetVendorCount(message.GetPlayerId())));

	std::vector<NetworkId> vendorList;
	std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::const_iterator const iterPlayer = m_playerVendorListMap.find(message.GetPlayerId());
	if (iterPlayer != m_playerVendorListMap.end())
	{
		for (std::map<NetworkId, AuctionLocation *>::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation)
		{
			vendorList.push_back(iterAuctionLocation->first);
		}
	}

	OnGetPlayerVendorCount(message.GetResponseId(), message.GetTrackId(), message.GetPlayerId(), vendorList.size(), vendorList);
}

// ----------------------------------------------------------------------

void AuctionMarket::UpdateVendorSearchOption(const UpdateVendorSearchOptionMessage &message)
{

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : TrackId : %d\n", message.GetTrackId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : Enabled : %d\n", message.GetEnabled()));

	AuctionLocation &loc = GetLocation(message.GetVendorId());
	loc.SetSearchedEnabled(message.GetEnabled());
	CMUpdateLocationMessage msg(
		loc.GetLocationId(),
		loc.GetOwnerId(),
		loc.GetLocationString(),
		loc.GetSalesTax(),
		loc.GetSalesTaxBankId(),
		loc.GetEmptyDate(),
		loc.GetLastAccessDate(),
		loc.GetInactiveDate(),
		loc.GetFullStatus(),
		message.GetEnabled(),
		loc.GetEntranceCharge()
	);

	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	if (dbServer)
		dbServer->send(msg, true);

	OnUpdateVendorSearchOptionMessage reply(message.GetPlayerId(), message.GetEnabled());

	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId());
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnUpdateVendorSearchOptionMessage callback to GamerServer ID: %d\n", message.GetTrackId()));
		gameServerConn->send(reply, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", message.GetTrackId()));
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::SetEntranceCharge(const SetEntranceChargeMessage &message)
{

	bool tempv = m_showAllDebugInfo;
	m_showAllDebugInfo = true;
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : TrackId : %d\n", message.GetTrackId()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : EntranceCharge : %d\n", message.GetEntranceCharge()));
	m_showAllDebugInfo = tempv;

	AuctionLocation &loc = GetLocation(message.GetVendorId());
	loc.SetEntranceCharge(message.GetEntranceCharge());
	CMUpdateLocationMessage msg(
		loc.GetLocationId(),
		loc.GetOwnerId(),
		loc.GetLocationString(),
		loc.GetSalesTax(),
		loc.GetSalesTaxBankId(),
		loc.GetEmptyDate(),
		loc.GetLastAccessDate(),
		loc.GetInactiveDate(),
		loc.GetFullStatus(),
		loc.GetSearchEnabled(),
		loc.GetEntranceCharge()
	);

	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	if (dbServer)
		dbServer->send(msg, true);

}

// ----------------------------------------------------------------------

void AuctionMarket::DeleteCharacter(const DeleteCharacterMessage &message)
{
	std::map<NetworkId, Auction *>::iterator auctionsIterator = m_auctions.begin();
	std::vector<std::map<NetworkId, Auction *>::iterator> auctionsToDelete;

	while (auctionsIterator != m_auctions.end())
	{
		if ((*auctionsIterator).second->GetItem().GetOwnerId() == message.getCharacterId())
			auctionsToDelete.push_back(auctionsIterator);
		++auctionsIterator;
	}

	std::vector<std::map<NetworkId, Auction *>::iterator>::iterator iter = auctionsToDelete.begin();
	while (iter != auctionsToDelete.end())
	{
		auctionsIterator = (*iter);
		LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because character %s is deleted.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), message.getCharacterId().getValueString().c_str()));
		LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because character %s is deleted.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), message.getCharacterId().getValueString().c_str()));
		DestroyAuction(auctionsIterator);
		++iter;
	}

}

// ----------------------------------------------------------------------

void AuctionMarket::SendItemTypeMap(GameServerConnection &gameServerConnection)
{
	GenericValueTypeMessage<std::pair<int, std::map<int, std::set<int> > > > msg("CommoditiesItemTypeMap", std::make_pair(m_itemTypeMapVersionNumber, m_itemTypeMap));
	gameServerConnection.send(msg, true);
}

// ----------------------------------------------------------------------

void AuctionMarket::AddResourceType(int resourceClassCrc, const std::string & resourceName)
{
	std::set<std::string> & resourceNameList = m_resourceTypeMap[resourceClassCrc];
	if (resourceNameList.count(resourceName) == 0)
	{
		++m_resourceTypeMapVersionNumber;
		IGNORE_RETURN(resourceNameList.insert(resourceName));

		GenericValueTypeMessage<std::pair<int, std::pair<int, std::string> > > msg("CommoditiesResourceTypeAdded", std::make_pair(m_resourceTypeMapVersionNumber, std::make_pair(resourceClassCrc, resourceName)));
		CommodityServer::getInstance().sendToAllGameServers(msg);	
	}
}

// ----------------------------------------------------------------------

void AuctionMarket::SendResourceTypeMap(GameServerConnection &gameServerConnection)
{
	GenericValueTypeMessage<std::pair<int, std::map<int, std::set<std::string> > > > msg("CommoditiesResourceTypeMap", std::make_pair(m_resourceTypeMapVersionNumber, m_resourceTypeMap));
	gameServerConnection.send(msg, true);
}

// ----------------------------------------------------------------------

void AuctionMarket::RemoveFromAuctionTimerPriorityQueue(int timer, const NetworkId & item)
{
	m_priorityQueueAuctionTimer.erase(std::make_pair(timer, item));
}

// ----------------------------------------------------------------------

void AuctionMarket::AddAuctionToCompletedAuctionsList(const Auction & auction)
{
	m_completedAuctions.push_back(auction.GetItem().GetItemId());
}

// ======================================================================
//
// AuctionMarket Message Callback Handlers
//
// ======================================================================

void AuctionMarket::OnAddAuction(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  ownerId,
	const std::string & ownerName,
	const NetworkId &  vendorId,
	const std::string & location
)
{
	OnAddAuctionMessage message(responseId, result, itemId, ownerId, ownerName, vendorId, location);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAddAuctionMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", trackId));
		}


}

void AuctionMarket::OnAddBid(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  ownerId,
	const NetworkId &  itemId,
	const NetworkId &  bidderId,
	const NetworkId &  previousBidderId,
	int bidAmount,
	int previousBidAmount,
	int maxProxyBid,
	const std::string & location,
	int itemNameLength,
	const Unicode::String & itemName,
	int salesTaxAmount,
	const NetworkId &  salesTaxBankId
)
{
	OnAddBidMessage message(responseId, result, itemId, ownerId, bidderId, previousBidderId, bidAmount, previousBidAmount, maxProxyBid, location, itemNameLength, itemName, salesTaxAmount, salesTaxBankId);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAddBidMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddBidMessage.\n", trackId));
		}

}

void AuctionMarket::OnCancelAuction(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId,
	const NetworkId &  highBidderId,
	int highBid,
	const std::string & location
)
{
	OnCancelAuctionMessage message(responseId, result, itemId, playerId, highBidderId, highBid, location);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCancelAuctionMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCancelAuctionMessage.\n", trackId));
		}

}

void AuctionMarket::OnAcceptHighBid(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId
)
{
	OnAcceptHighBidMessage message(responseId, result, itemId, playerId);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAcceptHighBidMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAcceptHighBidMessage.\n", trackId));
		}


}

void AuctionMarket::OnQueryAuctionHeaders(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  playerId,
	int queryType,
	std::vector<AuctionDataHeader> & auctions,
	unsigned int queryOffset,
	bool hasMorePages
)
{
	OnQueryAuctionHeadersMessage message(responseId, result, playerId, queryType, auctions, queryOffset, hasMorePages);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnQueryAuctionHeadersMessage callback to GamerServer ID: %d.\n\n", trackId));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : QueryType : %d.\n", message.GetQueryType()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : NumAuctions : %d.\n", message.GetNumAuctions()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : GetResultCode : %d.\n", message.GetResultCode()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : QueryOffset : %u.\n", message.GetQueryOffset()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : HasMorePages : %d.\n", message.HasMorePages()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : ResponseId : %d.\n", message.GetResponseId()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : TrackId : %d.\n", message.GetTrackId()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : Auctions : %d.\n", message.GetAuctionData().size()));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnQueryAuctionHeadersMessage.\n", trackId));
		}

}

void AuctionMarket::OnGetItemDetails(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId,
	int userDescriptionLength,
	const Unicode::String & userDescription,
	int oobDataLength,
	const Unicode::String & oobData,
	std::vector<std::pair<std::string, Unicode::String> > const & attributes
)
{
	OnGetItemDetailsMessage message(responseId, result, itemId, playerId, userDescriptionLength, userDescription, oobDataLength, oobData, attributes);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetItemDetailsMessage callback to GamerServer ID: %d.\n", trackId));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : Result : %d.\n", message.GetResultCode()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str()));
//			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobLength : %d.\n", message.GetOobLength()));
//			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobActualLength : %d.\n", message.GetOobData().size()));
//			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobData 	: "));
//			if (m_showAllDebugInfo)
//			{
//				Unicode::String temp = message.GetOobData();
//				Unicode::String::iterator i = temp.begin();
//				while (i != temp.end())
//				{	printf(" %X", (*i));
//					++i;
//				}
//				printf("\n");
//			}
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : ResponseId : %d.\n", message.GetResponseId()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : TrackId 	: %d.\n", message.GetTrackId()));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetItemDetailsMessage.\n", trackId));
		}


}

void AuctionMarket::OnAuctionExpired(
	const NetworkId &  ownerId,
	bool sold, const int flags,
	const NetworkId &  buyerId,
	int highBidAmount,
	const NetworkId &  itemId,
	int highBidMaxProxy,
	const std::string & location,
	bool immediate,
	int itemNameLength,
	const Unicode::String & itemName,
	const NetworkId &  itemOwnerId,
	int track_id,
	bool sendSellerMail
)
{

	OnAuctionExpiredMessage message(ownerId, sold, buyerId, highBidAmount, itemId, highBidMaxProxy, location, immediate, itemNameLength, itemName, sendSellerMail);
	message.SetTrackId(track_id);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(track_id);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAuctionExpiredMessage callback to GamerServer ID: %d.\n\n", track_id));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : BuyerId : %s.\n", message.GetBuyerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : Bid : %d.\n", message.GetBid()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : MaxProxyBid : %d.\n", message.GetMaxProxyBid()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : Location : %s.\n", message.GetLocation().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : IsSold : %d.\n", message.IsSold()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : IsImmediate : %d.\n", message.IsImmediate()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ResponseId : %d.\n", message.GetResponseId()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : TrackId : %d.\n", message.GetTrackId()));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAuctionExpiredMessage.\n", track_id));
		}

	if (sold)
	{
		AuctionLocation &auctionLocation = GetLocation(location);
		if (!auctionLocation.IsOwner(ownerId))
		{
			ModifyAuctionCount(ownerId, -1);
		}
		if (!auctionLocation.IsOwner(buyerId))
		{
			ModifyAuctionCount(buyerId, 1);
		}
		const_cast<NetworkId &>(ownerId) = buyerId;
	}

	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateAuctionMessage.\n"));
	CMUpdateAuctionMessage msg(
		itemId,
		itemOwnerId,
		(flags & (~3))
	);
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Id : %s.\n", msg.GetItemId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Item Owner : %s.\n", msg.GetOwnerId().getValueString().c_str()));
	DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Flags : %d.\n", msg.GetFlags()));

	DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer();
	if (dbServer)
		dbServer->send(msg, true);
}

void AuctionMarket::OnItemExpired(
	const NetworkId &  ownerId,
	const NetworkId &  itemId,
	int itemNameLength,
	const Unicode::String & itemName,
	const std::string & locationName,
	const NetworkId & locationId
)
{
	OnItemExpiredMessage message(ownerId, itemId, itemNameLength, itemName, locationName, locationId);
	message.SetTrackId(-1);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(-1);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnItemExpiredMessage callback to GamerServer ID: %d.\n\n", -1));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ResponseId : %d.\n", message.GetResponseId()));
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : TrackId : %d.\n", message.GetTrackId()));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnItemExpiredMessage.\n", -1));
		}


}

void AuctionMarket::OnGetItem(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId,
	const std::string & location
)
{
	OnGetItemMessage message(responseId, result, itemId, playerId, location);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetItemMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetItemMessage.\n", trackId));
		}


}

void AuctionMarket::OnCreateVendorMarket(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  ownerId,
	const std::string & location
)
{
	OnCreateVendorMarketMessage message(responseId, result, ownerId, location);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCreateVendorMarketMessage callback to GamerServer ID: %d.\n", trackId));
		gameServerConn->send(message, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCreateVendorMarketMessage.\n", trackId));
	}


}

void AuctionMarket::OnVendorRefuseItem(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId,
	const NetworkId &  creatorId
)
{
	OnVendorRefuseItemMessage message(responseId, result, itemId, playerId, creatorId);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnVendorRefuseItemMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnVendorRefuseItemMessage.\n", trackId));
		}

}

void AuctionMarket::OnGetVendorOwner(
	int trackId,
	int result,
	int responseId,
	const NetworkId &  ownerId,
	const NetworkId &  requesterId,
	const std::string & location
)
{
	OnGetVendorOwnerMessage message(responseId, result, ownerId, requesterId, location);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetVendorOwnerMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetVendorOwnerMessage.\n", trackId));
		}
}

void AuctionMarket::OnPermanentAuctionPurchased(
	int trackId,
	const NetworkId &  ownerId,
	const NetworkId &  buyerId,
	int price,
	const NetworkId &  itemId,
	const std::string & location,
	int itemNameLength,
	const Unicode::String & itemName,
	std::vector<std::pair<std::string, Unicode::String> > const & attributes
	)
{
	OnPermanentAuctionPurchasedMessage message(ownerId, buyerId, price, itemId, location, itemNameLength, itemName, attributes);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnPermanentAuctionPurchasedMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnPermanentAuctionPurchasedMessage.\n", trackId));
		}

}

void AuctionMarket::OnGetVendorValue(
	int trackId,
	int responseId,
	const std::string & location,
	int value)
{
	OnGetVendorValueMessage message(responseId, location, value);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetVendorValueMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetVendorValueMessage.\n", trackId));
		}

}

void AuctionMarket::OnCleanupInvalidItemRetrieval(
	int trackId,
	int responseId,
	const NetworkId &  itemId,
	const NetworkId &  playerId,
	const NetworkId &  creatorId,
	int reimburseAmt)
{
	OnCleanupInvalidItemRetrievalMessage message(responseId, itemId, playerId, creatorId, reimburseAmt);
	message.SetTrackId(trackId);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
		{
			DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCleanupInvalidItemRetrievalMessage callback to GamerServer ID: %d.\n", trackId));
			gameServerConn->send(message, true);
		}
	else
		{
			WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCleanupInvalidItemRetrievalMessage.\n", trackId));
		}

}

void    AuctionMarket::OnQueryVendorItemCount (
	const int responseId,
	const int trackId,
	const NetworkId &vendorId,
	const int itemCount,
	const bool searchEnabled)
{
	OnQueryVendorItemCountReplyMessage message(responseId, vendorId, itemCount, searchEnabled);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnQueryVendorItemCountMessage callback to GamerServer ID: %d.\n", trackId));
		gameServerConn->send(message, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnQueryVendorItemCountMessage.\n", trackId));
	}
}

void AuctionMarket::OnGetPlayerVendorCount (
	const int responseId,
	const int trackId,
	const NetworkId &playerId,
	const int vendorCount,
	std::vector<NetworkId> vendorList)
{
	OnGetPlayerVendorCountMessage message(responseId, playerId, vendorCount, vendorList);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetPlayerVendorCountMessage callback to GamerServer ID: %d.\n", trackId));
		gameServerConn->send(message, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetPlayerVendorCountMessage.\n", trackId));
	}
}

void    AuctionMarket::OnVendorStatusChange (
	int trackId,
	const NetworkId &vendorId,
	int newStatus)
{
	if (newStatus == ARC_VendorRemoved)
	{
		RemovePlayerVendor(GetLocation(vendorId).GetOwnerId(), vendorId);
	}
	VendorStatusChangeMessage message(vendorId, newStatus);
	GameServerConnection*  gameServerConn;
	gameServerConn = CommodityServer::getInstance().getGameServer(trackId);
	if (gameServerConn)
	{
		DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending VendorStatusChangeMessage callback to GamerServer ID: %d, vendorId = %s, newStatus = %d.\n", trackId, vendorId.getValueString().c_str(), newStatus));
		gameServerConn->send(message, true);
	}
	else
	{
		WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send VendorStatusChangeMessage.\n", trackId));
	}
}

void static decodeOOB(const std::string & UTF8String, Unicode::String & UniString)
{
	std::string::const_iterator c = UTF8String.begin();
	std::string tempstring;
	unsigned short unicharvalue;
	char * pEnd;

	while (c != UTF8String.end())
	{
		tempstring.push_back(*c);
		if (tempstring.length() == 4)
		{
			unicharvalue = static_cast<unsigned short>(strtoul(tempstring.c_str(), &pEnd, 16));
			if (pEnd)
			{
				// WARNING(true, ("[Commodities Server ] : Conversion of string hex values to unsigned short failed in: TaskGetAuctionList::decodeOOB.\n"));
			}
			UniString.push_back(unicharvalue);
			tempstring.clear();
		}
		c++;
	}
	if (tempstring.length() != 0)
	{
		WARNING(true, ("[Commodities Server ] : Unconverted OOB data in - TaskGetAuctionList::decodeOOB.\n"));
	}
}

void	AuctionMarket::onReceiveAuctionLocations     (const NetworkId &locationId, const std::string &locationName, const NetworkId &ownerId, const int salesTax, const NetworkId &salesTaxBankId, const int emptyDate, const int lastAccessDate, const int inactiveDate, const int status, const bool searchEnabled, const int entranceCharge)
{

    	AuctionLocation *auctionLocation = new AuctionLocation(locationId, locationName, ownerId, salesTax, salesTaxBankId, emptyDate, lastAccessDate, inactiveDate, status, searchEnabled, entranceCharge);

	m_locationIdMap.insert(std::make_pair(auctionLocation->GetLocationId(), auctionLocation));
	if ((ownerId != zeroNetworkId) && (auctionLocation->GetStatus() < REMOVED))
	{
		AddPlayerVendor(ownerId, locationId, auctionLocation);
	}
}

void AuctionMarket::onReceiveMarketAuctions (const NetworkId &itemId, const NetworkId &ownerId, const NetworkId &creatorId, const NetworkId &locationId, const int minBid, const int buyNowPrice, const int auctionTimer, const std::string &oob, const Unicode::String &userDescription, const int category, const int itemTemplateId, const Unicode::String &itemName, const int itemTimer, const int active, const int itemSize)
{
	AuctionLocation &location = GetLocation(locationId);

	Unicode::String oobData;
	decodeOOB(oob, oobData);

	std::vector<std::pair<std::string, Unicode::String> > attributes;

	Auction *auction = new Auction(
				creatorId,
				minBid,
				auctionTimer,
				itemId,
				itemName.size(),
				itemName,
				category,
				itemTemplateId,
				itemTimer,
				itemSize,
				location,
				active,
				buyNowPrice,
				userDescription.size(),
				userDescription,
				oobData.size(),
				oobData,
				attributes,
				(active & 1),
				(active & 2));

	auction->GetItem().SetOwnerId(ownerId);

	if ((auction->GetItem().GetItemTemplateId() != 0) && (auction->GetItem().GetCategory() != 0))
	{
		std::set<int> & itemTypeList = m_itemTypeMap[auction->GetItem().GetCategory()];
		if (itemTypeList.count(auction->GetItem().GetItemTemplateId()) == 0)
		{
			++m_itemTypeMapVersionNumber;
			IGNORE_RETURN(itemTypeList.insert(auction->GetItem().GetItemTemplateId()));
		}
	}

	m_auctions.insert(std::make_pair(auction->GetItem().GetItemId(), auction));

	std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory());
	std::map<std::string, int>::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType);
	if (iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end())
	{
		++iterAuctionsCountByGameObjectType->second;
		m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType);

		if (GameObjectTypes::isSubType(auction->GetItem().GetCategory()))
		{
			std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory()));
			std::map<std::string, int>::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType);
			if (iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end())
			{
				++iterAuctionsCountByParentGameObjectType->second;
				m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType);
			}
		}
	}

	if (!location.IsOwner(auction->GetItem().GetOwnerId()))
	{
		ModifyAuctionCount(auction->GetItem().GetOwnerId(), 1);
	}

	location.AddAuction(auction);
	AddAuctionToPriorityQueue(*auction);

	if (auction->IsActive() && auction->IsSold())
		AddAuctionToCompletedAuctionsList(*auction);
}

void AuctionMarket::onReceiveMarketAuctionAttributes(const NetworkId &itemId, const std::string &attributeName, const Unicode::String &attributeValue)
{
	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(itemId);

	if (iter != m_auctions.end())
	{
		Auction *auction = (*iter).second;

		auction->AddAttributes(attributeName, attributeValue);
	}
	else
	{
		WARNING(true,("[Commodities Server] : There are orphaned auction attributes records for item %s.", itemId.getValueString().c_str()));
	}
}

void	AuctionMarket::onReceiveMarketAuctionBids    (const NetworkId &itemId, const NetworkId &bidderId, const int bid, const int maxProxyBid)
{
	std::map<NetworkId, Auction *>::iterator iter = m_auctions.find(itemId);

	if (iter != m_auctions.end())
	{
		Auction *auction = (*iter).second;

		auction->AddLoadedBid(bidderId, bid, maxProxyBid);
	}
	else
	{
		WARNING(true,("[Commodities Server] : There are orphaned bid records for item %s.", itemId.getValueString().c_str()));
	}
}

void	AuctionMarket::printAuctionTables()
{

	DEBUG_REPORT_LOG(true, ("  Print AUCTION_LOCATIONS data:\n"));
	std::map<NetworkId, AuctionLocation *>::iterator auctionLocationIterator =
		m_locationIdMap.begin();
	while (auctionLocationIterator != m_locationIdMap.end())
	{
		DEBUG_REPORT_LOG(true, ("    LocId = %s, LocName = %s\n      OwnerId = %s, SalesTax = %d, SalesTaxBankId = %s, EntranceCharge = %d\n", auctionLocationIterator->second->GetLocationId().getValueString().c_str(), auctionLocationIterator->second->GetLocationString().c_str(), auctionLocationIterator->second->GetOwnerId().getValueString().c_str(), auctionLocationIterator->second->GetSalesTax(), auctionLocationIterator->second->GetSalesTaxBankId().getValueString().c_str(), auctionLocationIterator->second->GetEntranceCharge()));
		++auctionLocationIterator;
	}

	DEBUG_REPORT_LOG(true, ("  Print MARKET_AUCTIONS data:\n"));
	std::map<NetworkId, Auction *>::iterator marketAuctionsIterator = m_auctions.begin();
	while (marketAuctionsIterator != m_auctions.end())
	{
		Auction *auction = marketAuctionsIterator->second;
		UNREF(auction);
		DEBUG_REPORT_LOG(true, ("    ItemId = %s, OwnerId = %s, CreatorId = %s, LocId = %s\n      MinBid = %d, BuyNowPrice = %d, AuctionTimer = %d, Category = %d\n",
		auction->GetItem().GetItemId().getValueString().c_str(),
		auction->GetItem().GetOwnerId().getValueString().c_str(),
		auction->GetCreatorId().getValueString().c_str(),
		auction->GetLocation().GetLocationId().getValueString().c_str(),
		auction->GetMinBid(),
		auction->GetBuyNowPrice(),
		auction->GetAuctionTimer(),
		auction->GetFlags()));
		++marketAuctionsIterator;
	}
}

void AuctionMarket::VerifyExcludedGotTypes(std::map<int, std::string> const & excludedGotTypes)
{
	std::set<int> processedGotTypes;

	int itemCategory, itemGeneralCategory;
	std::map<int, std::string>::const_iterator iterFind;
	std::map<NetworkId, Auction *>::const_iterator marketAuctionsIterator = m_auctions.begin();
	while (marketAuctionsIterator != m_auctions.end())
	{
		AuctionItem const & auctionItem = marketAuctionsIterator->second->GetItem();
		itemCategory = auctionItem.GetCategory();
		if (processedGotTypes.count(itemCategory) == 0)
		{
			IGNORE_RETURN(processedGotTypes.insert(itemCategory));

			iterFind = excludedGotTypes.find(itemCategory);
			if (iterFind != excludedGotTypes.end())
			{
				LOG("CustomerService", ("CommoditiesMissingCategory:Item %s (%s) is in excluded category %d (%s)",
					auctionItem.GetItemId().getValueString().c_str(),
					Unicode::wideToNarrow(auctionItem.GetName()).c_str(),
					iterFind->first,
					iterFind->second.c_str()));
			}

			itemGeneralCategory = itemCategory & 0xffffff00;
			if (itemCategory != itemGeneralCategory)
			{
				// general category
				iterFind = excludedGotTypes.find(itemGeneralCategory);
				if (iterFind != excludedGotTypes.end())
				{
					LOG("CustomerService", ("CommoditiesMissingCategory:Item %s (%s) is in excluded general category %d (%s)",
						auctionItem.GetItemId().getValueString().c_str(),
						Unicode::wideToNarrow(auctionItem.GetName()).c_str(),
						iterFind->first,
						iterFind->second.c_str()));
				}
			}
		}

		++marketAuctionsIterator;
	}
}

void AuctionMarket::VerifyExcludedResourceClasses(std::set<std::string> const & excludedResourceClasses)
{
	int excludedClassCrc;
	for (std::set<std::string>::const_iterator iterExcluded = excludedResourceClasses.begin(); iterExcluded != excludedResourceClasses.end(); ++iterExcluded)
	{
		excludedClassCrc = static_cast<int>(Crc::calculate(iterExcluded->c_str()));

		for (std::map<NetworkId, AuctionLocation *>::iterator locationIter = m_locationIdMap.begin(); locationIter != m_locationIdMap.end(); ++locationIter)		
		{
			std::map<NetworkId, Auction *> const & auctionsResourceContainer = locationIter->second->GetAuctionsResourceContainer();
			for (std::map<NetworkId, Auction *>::const_iterator auctionIter = auctionsResourceContainer.begin(); auctionIter != auctionsResourceContainer.end(); ++auctionIter)
			{
				AuctionItem const & auctionItem = auctionIter->second->GetItem();
				if (IsResourceClassDerivedFrom(auctionItem.GetResourceContainerClassCrc(), excludedClassCrc))
				{
					LOG("CustomerService", ("CommoditiesMissingResourceClass:Item %s (%s) is in excluded resource class (%s)",
						auctionItem.GetItemId().getValueString().c_str(),
						Unicode::wideToNarrow(auctionItem.GetName()).c_str(),
						iterExcluded->c_str()));
				}
			}
		}
	}
}

bool AuctionMarket::IsResourceClassDerivedFrom(int resourceClassCrc, int parentResourceClassCrc)
{
	if (resourceClassCrc == parentResourceClassCrc)
		return true;

	std::map<int, std::set<int> >::const_iterator iter = m_resourceTreeHierarchy.find(resourceClassCrc);
	if (iter == m_resourceTreeHierarchy.end())
		return false;

	return (iter->second.count(parentResourceClassCrc) > 0);
}

void AuctionMarket::SetResourceTreeHierarchy(std::map<int, std::set<int> > const & resourceTreeHierarchy)
{
	m_resourceTreeHierarchy = resourceTreeHierarchy;
}

void AuctionMarket::getItemAttributeData(int requestingGameServerId, const NetworkId & requester, const std::string & outputFileName, int gameObjectType, bool exactGameObjectTypeMatch, bool ignoreSearchableAttribute, int throttle) const
{
	if (getItemAttributeDataRequest)
	{
		if (getItemAttributeDataRequest->requester != requester)
		{
			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
		else if (getItemAttributeDataRequest->action != "GetItemAttributeData")
		{
			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
		else
		{
			getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId;
			getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle;

			getItemAttributeDataRequest->outputFileName = outputFileName;

			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "%s request modified.  outputFileName=(%s), gameObjectType=(%d, %s), exactGameObjectTypeMatch=(%s), ignoreSearchableAttribute=(%s), throttle=(%d), numberItemsProcessed=(%d), totalNumberOfItems=(%d).",
					getItemAttributeDataRequest->action.c_str(),
					getItemAttributeDataRequest->outputFileName.c_str(),
					getItemAttributeDataRequest->gameObjectType,
					GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(),
					(getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ),
					(getItemAttributeDataRequest->ignoreSearchableAttribute ? "yes" : "no"),
					getItemAttributeDataRequest->throttleNumberItemsPerFrame,
					getItemAttributeDataRequest->numberItemsProcessed,
					m_auctions.size());

				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
	}
	else
	{
		getItemAttributeDataRequest = new GetItemAttributeDataRequest();
		getItemAttributeDataRequest->action = "GetItemAttributeData";
		getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId;
		getItemAttributeDataRequest->requester = requester;
		getItemAttributeDataRequest->gameObjectType = gameObjectType;
		getItemAttributeDataRequest->exactGameObjectTypeMatch = exactGameObjectTypeMatch;
		getItemAttributeDataRequest->ignoreSearchableAttribute = ignoreSearchableAttribute;
		getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle;
		getItemAttributeDataRequest->numberItemsProcessed = 0;
		getItemAttributeDataRequest->lastItemProcessed = NetworkId::cms_invalid;

		getItemAttributeDataRequest->outputFileName = outputFileName;
		getItemAttributeDataRequest->allItemAttributes.clear();

		GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
		if (gameServerConn)
		{
			char buffer[2048];
			snprintf(buffer, sizeof(buffer)-1, "%s request accepted.  outputFileName=(%s), gameObjectType=(%d, %s), exactGameObjectTypeMatch=(%s), ignoreSearchableAttribute=(%s), throttle=(%d), totalNumberOfItems=(%d).",
				getItemAttributeDataRequest->action.c_str(),
				getItemAttributeDataRequest->outputFileName.c_str(),
				getItemAttributeDataRequest->gameObjectType,
				GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(),
				(getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ),
				(getItemAttributeDataRequest->ignoreSearchableAttribute ? "yes" : "no"),
				getItemAttributeDataRequest->throttleNumberItemsPerFrame,
				m_auctions.size());

			buffer[sizeof(buffer)-1] = '\0';

			GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer)));
			gameServerConn->send(msg, true);
		}
	}
}

void AuctionMarket::getItemAttributeDataValues(int requestingGameServerId, const NetworkId & requester, int gameObjectType, bool exactGameObjectTypeMatch, const std::string & attributeName, int throttle) const
{
	if (getItemAttributeDataRequest)
	{
		if (getItemAttributeDataRequest->requester != requester)
		{
			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
		else if (getItemAttributeDataRequest->action != "GetItemAttributeDataValues")
		{
			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
		else
		{
			getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId;
			getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle;

			GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
			if (gameServerConn)
			{
				char buffer[2048];
				snprintf(buffer, sizeof(buffer)-1, "%s request modified.  game object type=(%d, %s), exactGameObjectTypeMatch=(%s), attribute name=(%s), throttle=(%d), numberItemsProcessed=(%d), totalNumberOfItems=(%d).",
					getItemAttributeDataRequest->action.c_str(),
					getItemAttributeDataRequest->gameObjectType,
					GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(),
					(getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ),
					getItemAttributeDataRequest->attributeName.c_str(),
					getItemAttributeDataRequest->throttleNumberItemsPerFrame,
					getItemAttributeDataRequest->numberItemsProcessed,
					m_auctions.size());
				buffer[sizeof(buffer)-1] = '\0';

				GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer)));
				gameServerConn->send(msg, true);
			}
		}
	}
	else
	{
		getItemAttributeDataRequest = new GetItemAttributeDataRequest();
		getItemAttributeDataRequest->action = "GetItemAttributeDataValues";
		getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId;
		getItemAttributeDataRequest->requester = requester;
		getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle;
		getItemAttributeDataRequest->numberItemsProcessed = 0;
		getItemAttributeDataRequest->lastItemProcessed = NetworkId::cms_invalid;

		getItemAttributeDataRequest->gameObjectType = gameObjectType;
		getItemAttributeDataRequest->exactGameObjectTypeMatch = exactGameObjectTypeMatch;
		getItemAttributeDataRequest->attributeName = attributeName;
		getItemAttributeDataRequest->numberItemsMatchGameObjectType = 0;
		getItemAttributeDataRequest->attributeValue.clear();

		GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
		if (gameServerConn)
		{
			char buffer[2048];
			snprintf(buffer, sizeof(buffer)-1, "%s request accepted.  game object type=(%d, %s), exactGameObjectTypeMatch=(%s), attribute name=(%s), throttle=(%d), totalNumberOfItems=(%d).",
				getItemAttributeDataRequest->action.c_str(),
				getItemAttributeDataRequest->gameObjectType,
				GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(),
				(getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ),
				getItemAttributeDataRequest->attributeName.c_str(),
				getItemAttributeDataRequest->throttleNumberItemsPerFrame,
				m_auctions.size());
			buffer[sizeof(buffer)-1] = '\0';

			GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer)));
			gameServerConn->send(msg, true);
		}
	}
}

void AuctionMarket::getItemAttribute(int requestingGameServerId, const NetworkId & requester, const NetworkId & item) const
{
	std::map<NetworkId, Auction *>::const_iterator iterAuction = m_auctions.find(item);
	if (iterAuction != m_auctions.end())
	{
		GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
		if (gameServerConn)
		{
			std::string output;
			iterAuction->second->GetAttributes(output);

			GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, output));
			gameServerConn->send(msg, true);
		}
	}
	else
	{
		GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
		if (gameServerConn)
		{
			char buffer[2048];
			snprintf(buffer, sizeof(buffer)-1, "item (%s) is not in the commodities system", item.getValueString().c_str());
			buffer[sizeof(buffer)-1] = '\0';

			GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer)));
			gameServerConn->send(msg, true);
		}
	}
}

void AuctionMarket::getVendorInfoForPlayer(int requestingGameServerId, const NetworkId & requester, const NetworkId & player, bool godMode)
{
	// if vendor is specified for player, replace it with the vendor's owner
	NetworkId vendorOwner = player;
	if (vendorOwner != requester)
	{
		std::map<NetworkId, AuctionLocation *>::iterator const iterFind = m_locationIdMap.find(vendorOwner);
		if (iterFind != m_locationIdMap.end())
		{
			vendorOwner = iterFind->second->GetOwnerId();
		}
	}

	std::map<std::string, std::vector<std::string> > vendorInfo;
	int totalOfferCount = 0;
	int totalStockRoomCount = 0;
	std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::const_iterator const iterPlayer = m_playerVendorListMap.find(vendorOwner);
	if (iterPlayer != m_playerVendorListMap.end())
	{
		char buffer[64];
		std::string planet;
		std::string region;
		std::string name;
		NetworkId id;
		int x, z;
		int offerCount, stockRoomCount;

		unsigned int pos = 0;

		for (std::map<NetworkId, AuctionLocation *>::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation)
		{
			pos = 0;
			nextString(iterAuctionLocation->second->GetLocationString(), pos, planet, '.');
			nextString(iterAuctionLocation->second->GetLocationString(), pos, region, '.');
			nextString(iterAuctionLocation->second->GetLocationString(), pos, name, '.');
			nextOid(iterAuctionLocation->second->GetLocationString(), pos, id, '#');
			nextInt(iterAuctionLocation->second->GetLocationString(), pos, x, ',');
			nextInt(iterAuctionLocation->second->GetLocationString(), pos, z, ',');

			if ((name.find("Vendor: ") == 0) && (name.size() > 8))
			{
				name = name.substr(8);
			}

			vendorInfo["name"].push_back(name);

			if (iterAuctionLocation->second->IsPacked())
			{
				planet = "Datapad";
			}
			else
			{
				planet = Unicode::wideToNarrow(StringId("planet_n", planet).localize());

				snprintf(buffer, sizeof(buffer)-1, " (%d, %d)", x, z);
				buffer[sizeof(buffer)-1] = '\0';

				planet += buffer;
			}

			if (godMode)
			{
				planet += " (";
				planet += iterAuctionLocation->second->GetLocationString();
				planet += ")";
			}

			vendorInfo["location"].push_back(planet);

			snprintf(buffer, sizeof(buffer)-1, "%d", (iterAuctionLocation->second->GetSalesTax() / 100));
			buffer[sizeof(buffer)-1] = '\0';
			vendorInfo["tax"].push_back(buffer);

			vendorInfo["taxCity"].push_back(iterAuctionLocation->second->GetSalesTaxBankId().getValueString());

			if (iterAuctionLocation->second->GetEmptyDate() > 0)
			{
				vendorInfo["emptyDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast<time_t>(iterAuctionLocation->second->GetEmptyDate())));
			}
			else
			{
				vendorInfo["emptyDate"].push_back("");
			}

			if (iterAuctionLocation->second->GetLastAccessDate() > 0)
			{
				vendorInfo["lastAccessDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast<time_t>(iterAuctionLocation->second->GetLastAccessDate())));
			}
			else
			{
				vendorInfo["lastAccessDate"].push_back("");
			}

			if (iterAuctionLocation->second->GetInactiveDate() > 0)
			{
				vendorInfo["inactiveDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast<time_t>(iterAuctionLocation->second->GetInactiveDate())));
			}
			else
			{
				vendorInfo["inactiveDate"].push_back("");
			}

			vendorInfo["status"].push_back(vendorStatus[iterAuctionLocation->second->GetStatus()]);

			if (iterAuctionLocation->second->IsPacked())
			{
				vendorInfo["searchable"].push_back("no");
			}
			else
			{
				vendorInfo["searchable"].push_back(iterAuctionLocation->second->GetSearchEnabled() ? "yes" : "no");
			}

			snprintf(buffer, sizeof(buffer)-1, "%d", iterAuctionLocation->second->GetEntranceCharge());
			buffer[sizeof(buffer)-1] = '\0';
			vendorInfo["entranceCharge"].push_back(buffer);

			snprintf(buffer, sizeof(buffer)-1, "%d", iterAuctionLocation->second->GetAuctionItemCount());
			buffer[sizeof(buffer)-1] = '\0';
			vendorInfo["itemCount"].push_back(buffer);

			offerCount = 0;
			stockRoomCount = 0;
			std::map<NetworkId, Auction *> const & offers = iterAuctionLocation->second->GetVendorOffers();
			for (std::map<NetworkId, Auction *>::const_iterator iterOffer = offers.begin(); iterOffer != offers.end(); ++iterOffer)
			{
				if (iterOffer->second->GetItem().GetOwnerId() == vendorOwner)
				{
					stockRoomCount += iterOffer->second->GetItem().GetSize();
				}
				else if (iterOffer->second->IsActive())
				{
					offerCount += iterOffer->second->GetItem().GetSize();
				}
			}

			snprintf(buffer, sizeof(buffer)-1, "%d", offerCount);
			buffer[sizeof(buffer)-1] = '\0';
			vendorInfo["offerCount"].push_back(buffer);

			snprintf(buffer, sizeof(buffer)-1, "%d", stockRoomCount);
			buffer[sizeof(buffer)-1] = '\0';
			vendorInfo["stockRoomCount"].push_back(buffer);

			totalOfferCount += offerCount;
			totalStockRoomCount += stockRoomCount;
		}
	}

	GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
	if (gameServerConn)
	{
		char buffer[2048];

		if (requester == vendorOwner)
		{
			snprintf(buffer, sizeof(buffer)-1, "You currently have %d initialized vendors containing %d active items, %d stockroom items, and %d offered items.", GetVendorCount(vendorOwner), GetItemCount(vendorOwner), totalStockRoomCount, totalOfferCount);
			buffer[sizeof(buffer)-1] = '\0';
		}
		else
		{
			snprintf(buffer, sizeof(buffer)-1, "Player %s currently has %d initialized vendors containing %d active items, %d stockroom items, and %d offered items.", vendorOwner.getValueString().c_str(), GetVendorCount(vendorOwner), GetItemCount(vendorOwner), totalStockRoomCount, totalOfferCount);
			buffer[sizeof(buffer)-1] = '\0';
		}

		GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, std::map<std::string, std::vector<std::string> > > > const msg("GetVendorInfoForPlayerRsp", std::make_pair(std::make_pair(requester, std::string(buffer)), vendorInfo));
		gameServerConn->send(msg, true);
	}
}

void AuctionMarket::getAuctionLocationPriorityQueue(int requestingGameServerId, const NetworkId & requester, int count) const
{
	std::string output;
	char buffer[2048];
	int const timeNow = static_cast<int>(::time(nullptr));
	for (std::set<std::pair<int, NetworkId> >::const_iterator iterPQ = m_priorityQueueAuctionLocation.begin(); iterPQ != m_priorityQueueAuctionLocation.end(); ++iterPQ)
	{
		if (count <= 0)
			break;

		std::map<NetworkId, AuctionLocation *>::const_iterator iterAuctionLocation = m_locationIdMap.find((*iterPQ).second);
		if (iterAuctionLocation != m_locationIdMap.end())
		{
			if ((*iterPQ).first >= timeNow)
			{
				snprintf(buffer, sizeof(buffer)-1, "next update in (%d, %s) for auction location (%s, %s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast<unsigned int>((*iterPQ).first - timeNow)).c_str(), (*iterPQ).second.getValueString().c_str(), iterAuctionLocation->second->GetLocationString().c_str());
				buffer[sizeof(buffer)-1] = '\0';
			}
			else
			{
				snprintf(buffer, sizeof(buffer)-1, "next update in (%d, -%s) for auction location (%s, %s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast<unsigned int>(timeNow - (*iterPQ).first)).c_str(), (*iterPQ).second.getValueString().c_str(), iterAuctionLocation->second->GetLocationString().c_str());
				buffer[sizeof(buffer)-1] = '\0';
			}
		}
		else
		{
			if ((*iterPQ).first >= timeNow)
			{
				snprintf(buffer, sizeof(buffer)-1, "next update in (%d, %s) for auction location (%s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast<unsigned int>((*iterPQ).first - timeNow)).c_str(), (*iterPQ).second.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';
			}
			else
			{
				snprintf(buffer, sizeof(buffer)-1, "next update in (%d, -%s) for auction location (%s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast<unsigned int>(timeNow - (*iterPQ).first)).c_str(), (*iterPQ).second.getValueString().c_str());
				buffer[sizeof(buffer)-1] = '\0';
			}
		}

		output += buffer;
		output += "\r\n";

		--count;
	}

	GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId);
	if (gameServerConn)
	{
		GenericValueTypeMessage<std::pair<NetworkId, std::string> > const msg("DisplayStringForPlayer", std::make_pair(requester, output));
		gameServerConn->send(msg, true);
	}
}

void AuctionMarket::BuildAuctionsSearchableAttributeList()
{
	for (std::map<NetworkId, Auction *>::iterator i = m_auctions.begin(); i != m_auctions.end(); ++i)
		i->second->BuildSearchableAttributeList();
}

void AuctionMarket::addAuctionLocationToLocationIndex(const AuctionLocation * auctionLocation)
{
	if (!auctionLocation)
		return;

	if (!auctionLocation->IsVendorMarket())
	{
		m_allBazaar[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
		(m_bazaarByPlanet[auctionLocation->GetLocationPlanet()])[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
		(m_bazaarByRegion[std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())])[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
	}
	else if (auctionLocation->GetSearchEnabled() && !auctionLocation->IsPacked())
	{
		m_allSearchableVendor[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
		(m_searchableVendorByPlanet[auctionLocation->GetLocationPlanet()])[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
		(m_searchableVendorByRegion[std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())])[auctionLocation->GetLocationId()] = const_cast<AuctionLocation *>(auctionLocation);
	}
}

void AuctionMarket::removeAuctionLocationFromLocationIndex(const AuctionLocation * auctionLocation)
{
	if (!auctionLocation)
		return;

	{
		m_allBazaar.erase(auctionLocation->GetLocationId());
	}

	{
		std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_bazaarByPlanet.find(auctionLocation->GetLocationPlanet());
		if (iterFind != m_bazaarByPlanet.end())
		{
			iterFind->second.erase(auctionLocation->GetLocationId());
			if (iterFind->second.empty())
			{
				m_bazaarByPlanet.erase(iterFind);
			}
		}
	}

	{
		std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_bazaarByRegion.find(std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion()));
		if (iterFind != m_bazaarByRegion.end())
		{
			iterFind->second.erase(auctionLocation->GetLocationId());
			if (iterFind->second.empty())
			{
				m_bazaarByRegion.erase(iterFind);
			}
		}
	}

	{
		m_allSearchableVendor.erase(auctionLocation->GetLocationId());
	}

	{
		std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_searchableVendorByPlanet.find(auctionLocation->GetLocationPlanet());
		if (iterFind != m_searchableVendorByPlanet.end())
		{
			iterFind->second.erase(auctionLocation->GetLocationId());
			if (iterFind->second.empty())
			{
				m_searchableVendorByPlanet.erase(iterFind);
			}
		}
	}

	{
		std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iterFind = m_searchableVendorByRegion.find(std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion()));
		if (iterFind != m_searchableVendorByRegion.end())
		{
			iterFind->second.erase(auctionLocation->GetLocationId());
			if (iterFind->second.empty())
			{
				m_searchableVendorByRegion.erase(iterFind);
			}
		}
	}
}

void AuctionMarket::sanityCheckAuctionLocationBeingDestroyed(const AuctionLocation * auctionLocation)
{
	if (!auctionLocation)
		return;

	{
		removeAuctionLocationFromList(m_locationIdMap, auctionLocation);
	}

	{
		for (std::map<NetworkId, std::map<NetworkId, AuctionLocation *> >::iterator iter = m_playerVendorListMap.begin(); iter != m_playerVendorListMap.end(); ++iter)
		{
			removeAuctionLocationFromList(iter->second, auctionLocation);
		}
	}

	{
		removeAuctionLocationFromList(m_allBazaar, auctionLocation);
	}

	{
		for (std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iter = m_bazaarByPlanet.begin(); iter != m_bazaarByPlanet.end(); ++iter)
		{
			removeAuctionLocationFromList(iter->second, auctionLocation);
		}
	}

	{
		for (std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iter = m_bazaarByRegion.begin(); iter != m_bazaarByRegion.end(); ++iter)
		{
			removeAuctionLocationFromList(iter->second, auctionLocation);
		}
	}

	{
		removeAuctionLocationFromList(m_allSearchableVendor, auctionLocation);
	}

	{
		for (std::map<std::string, std::map<NetworkId, AuctionLocation *> >::iterator iter = m_searchableVendorByPlanet.begin(); iter != m_searchableVendorByPlanet.end(); ++iter)
		{
			removeAuctionLocationFromList(iter->second, auctionLocation);
		}
	}

	{
		for (std::map<std::pair<std::string, std::string>, std::map<NetworkId, AuctionLocation *> >::iterator iter = m_searchableVendorByRegion.begin(); iter != m_searchableVendorByRegion.end(); ++iter)
		{
			removeAuctionLocationFromList(iter->second, auctionLocation);
		}
	}
}

void AuctionMarket::getPlanetAndRegionFromLocationString(const std::string &locationName, std::string &planet, std::string &region)
{
	unsigned int pos = 0;
	nextString(locationName, pos, planet, '.');
	nextString(locationName, pos, region, '.');
}
