// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: ALL
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

#include <bdLobby/bdKeyArchive/bdKeyPairDict.h>
#include <bdLobby/bdRemoteTaskManager/bdRemoteTaskManager.h>

#define BD_LOG_LEVEL ("lobby/bdKeyArchive/bdKeyPairDict")

bdKeyPairDict::bdKeyPairDict()
{
}

bdKeyPairDict::~bdKeyPairDict()
{
}

void bdKeyPairDict::serialize(bdBitBufferRef buffer,
							  const bdBool isReadKeyPairs) const
{
	// server expects:
	// num entity ids
	// for each entityID
	//   entityID
	//   numKeyPairs
	//   all current entityID's keyPairs

	// count unique entityIDs
	bdUInt numEntityIDs = 0;

	// bdHashMap <"entityID, isTeam", "numKeys for that entityID">
	bdHashMap<bdEntityIDKey, bdUInt> entityIDs;

	Iterator it = getIterator();
	while(it)
	{
		const bdArchiveKey &key = getKey(it);
		bdUInt value = 0;

		bdEntityIDKey entityIDkey;
		entityIDkey.entityID = key.getEntityID();
		entityIDkey.isTeam = key.getIsTeam();

		if (entityIDs.get(entityIDkey, value))
		{
			// entityID is in hash, increment numKeys
			entityIDs.remove(entityIDkey);
			entityIDs.put(entityIDkey, value+1);
		}
		else
		{
			// entityID isn't in hash, its a new one

			// add it to hash
			entityIDs.put(entityIDkey, 1);

			// count it
			numEntityIDs++;
		}

		next(it);
	}
	releaseIterator(it);

	buffer->writeInt32(numEntityIDs);

	// now serialize entityIDs and keys
	Iterator entityIDit = entityIDs.getIterator();
	while(entityIDit)
	{
		// serialize current entityID & its numKeys

		bdEntityIDKey &currEntityIDKey = entityIDs.getKey(entityIDit);
		bdUInt numKeys = entityIDs.getValue(entityIDit);

		buffer->writeUInt64(currEntityIDKey.entityID);
		buffer->writeUInt64(currEntityIDKey.isTeam);

		buffer->writeUInt32(numKeys);

		// now serialise currEntityIDs keypairs
		Iterator it = getIterator();
		while(it)
		{
			const bdArchiveKey &key = getKey(it);
			const bdArchiveValue &value = getValue(it);

			if (key.getEntityID() == currEntityIDKey.entityID)
			{
				// just serialize keyname here
				bdString keyName = key.getKeyName();
				buffer->writeString(keyName);

				if (!isReadKeyPairs)
				{
					value.serialize(buffer);
				}
			}

			next(it);
		}
		releaseIterator(it);

		entityIDs.next(entityIDit);
	}
	entityIDs.releaseIterator(entityIDit);
}

bdBool bdKeyPairDict::deserialize(const bdUInt numEntityIDs, bdBitBufferRef buffer)
{
	// numResults = numEntityIDs returned
	bdBool ok = true;

	if(numEntityIDs > 0)
	{
		for(bdUInt i = 0; i < numEntityIDs; i++)
		{

			bdUInt64 entityID = 0;
			bdBool isTeam = false;
			bdUInt32 numKeyPairs = 0;

			ok = ok && buffer->readUInt64(entityID);
			ok = ok && buffer->readBool(isTeam);
			ok = ok && buffer->readUInt32(numKeyPairs);

			for (bdUInt j = 0; j < numKeyPairs; j++)
			{
				bdString keyName = "";
				ok = ok && buffer->readString(keyName);
				bdArchiveValue value;
				ok = ok && value.deserialize(buffer);
				if (ok)
				{
					bdArchiveKey key(entityID, isTeam, keyName);
					put(key, value);
				}

			}
		}
	}
	else
	{
		ok = false;
		BD_WARN(BD_LOG_LEVEL, "");
	}

	return ok;
}


bdBool bdKeyPairDict::handleResult(const bdUInt numEntityIDs,
									bdBitBufferRef buffer)
{
	// and deserialize
	bdBool ok = deserialize(numEntityIDs, buffer);
	return ok;
}
