//
// Asura_ServerEntity_AttractorController.cpp
//
// Created by Richard Rice - 09/05/2007
// 
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Entity/Attractors/Asura_ServerEntity_AttractorController.h"

#ifdef ASURA_USE_ATTRACTORS

#include "Attractors/Asura_Attractor_System.h"
#include "Attractors/Asura_Attractor_Data.h"
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Network/Asura_Message.h"

#ifdef ASURA_TOOLS
#include "EntityTemplate/Tools_EntityTemplate_System.h"
#endif

#ifdef ASURA_TOOLS
Asura_Hashed_List<Asura_ServerEntity_AttractorController> Asura_ServerEntity_AttractorController::s_xList( 5 );
#endif


Asura_ServerEntity_AttractorController::Asura_ServerEntity_AttractorController(Asura_Guid uGuid)
:Asura_Entity_Server(uGuid)
,m_uToolsAttractorID(0)
,m_uNumCompiledAttractorIDs(0)
,m_puCompiledAttractorIDs(0)
{
	Classification = AsuraEntityClass_AttractorController;

	#ifdef ASURA_USE_STREAMING
	//The streaming zone handlers should be set correctly at this point , so store the ID
	//for use when the entity gets triggered. RAR 13/11/2006
	m_uHandlerID = Asura_Attractor_System::GetInstance()->GetCurrentHandler().GetHandlerID();
	#endif

	
	SetNeverUpdateClient();
	SetNeverUpdates(true);

	#ifdef ASURA_TOOLS
	s_xList.AddToList(this);
	#endif
}

Asura_ServerEntity_AttractorController::~Asura_ServerEntity_AttractorController()
{
	#ifdef ASURA_TOOLS
	s_xList.RemoveFromList(this);
	#endif

	delete [] m_puCompiledAttractorIDs;
}

void Asura_ServerEntity_AttractorController::Create(Asura_Guid uGuid, Asura_Chunk_Stream& xStream)
{
	Asura_ServerEntity_AttractorController* pxEntity = new Asura_ServerEntity_AttractorController(uGuid);
	pxEntity->ReadFromChunkStream(xStream);
}


void Asura_ServerEntity_AttractorController::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	//check our version
	int iVersion;
	xStream >> iVersion;
	Asura_Assertf(iVersion <= CHUNK_VERSION,("Unknown chunk version %d for attractor controller",iVersion));

	//read parent
	PARENT::ReadFromChunkStream(xStream);

	//read the rest of the data for this entity
	xStream >> m_uToolsAttractorID;

	xStream >> m_uNumCompiledAttractorIDs;
	if(m_uNumCompiledAttractorIDs) m_puCompiledAttractorIDs = new u_int[m_uNumCompiledAttractorIDs];
	for(u_int i=0; i<m_uNumCompiledAttractorIDs; i++)
	{
		xStream >> m_puCompiledAttractorIDs[i];
	}
}

void Asura_ServerEntity_AttractorController::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	//save our version
	xStream << (int) CHUNK_VERSION;
	//save the parent
	PARENT::WriteToChunkStream(xStream);

	//save data for this entity
	xStream << m_uToolsAttractorID;

	xStream << m_uNumCompiledAttractorIDs;
	for(u_int i=0; i<m_uNumCompiledAttractorIDs; i++)
	{
		xStream << m_puCompiledAttractorIDs[i];
	}
}

bool Asura_ServerEntity_AttractorController::HandleMessage(const Asura_Message* pxMessage)
{
	if(IsDestroyed()) return true;

	if (pxMessage)
	{
		switch (pxMessage->GetMsgID())
		{
			case ASURA_MSG_ACTIVATE:
			case ASURA_MSG_DEACTIVATE:
			{
				//forward activate/deactivate message to client
				u_int uFlagToSet = ASURA_ATTRACTOR_FLAG_ACTIVE;
				u_int uFlags = (pxMessage->GetMsgID() == ASURA_MSG_ACTIVATE) ? uFlagToSet : 0;
				SendAttractorFlagMessage(uFlagToSet,uFlags);
				return true;
			}

			default :
				break;
		}
	}

	return false;
}

void Asura_ServerEntity_AttractorController::SendAttractorFlagMessage(u_int uFlagsToSet,u_int uFlags)
{
	if(!m_uNumCompiledAttractorIDs) return;

	u_int uMsgSize = sizeof(Asura_Message_AttractorFlags) + sizeof(u_int)*m_uNumCompiledAttractorIDs;

	Asura_Message* pxMsg = Asura_Network::CreateMessage( ASURA_MSG_ATTRACTOR_FLAGS,  uMsgSize);
	Asura_Message_AttractorFlags* pxMessageData = reinterpret_cast<Asura_Message_AttractorFlags*>( pxMsg->GetData() );

	pxMessageData->m_uFlagsToSet = uFlagsToSet;
	pxMessageData->m_uFlags = uFlags;
	pxMessageData->m_uNumAttractorIDs = m_uNumCompiledAttractorIDs;
	#ifdef ASURA_USE_STREAMING
	pxMessageData->m_uHandlerID = m_uHandlerID;
	#endif

	u_int* puAttractorIDs = reinterpret_cast<u_int*>(pxMessageData + 1);
	for (u_int u = 0; u < m_uNumCompiledAttractorIDs; ++u)
	{
		puAttractorIDs[u] = m_puCompiledAttractorIDs[u];
	}

	pxMsg->To = ASURA_GUID_ALL_CLIENTMACHINES;
	pxMsg->From = GetGuid();

	Asura_Network::Send(pxMsg);
}


#ifdef ASURA_TOOLS

bool Asura_ServerEntity_AttractorController::CanBeIncludedInTemplate() const 
{
	return Classification == AsuraEntityClass_AttractorController;
}

void Asura_ServerEntity_AttractorController::ApplyChangesForTemplateInstance(class Tools_EntityTemplateInstance* pxInstance)
{
	PARENT::ApplyChangesForTemplateInstance(pxInstance);

	m_uToolsAttractorID = pxInstance->ConvertAttractorID(m_uToolsAttractorID);

	//The list of compiled attractor IDs will also be wrong , but the above function won't work with them ,and
	//they will get recalculated in the export process anyway... so it shouldn't matter.

}
#endif // ASURA_TOOLS




#endif //ASURA_USE_ATTRACTORS
