
////////////////////////////////////////////////////////////////////////////////
//
// Asura_ServerEntity_FMVSpeaker.cpp
// Author    : Jason Turner
// Copyright (C) 2009 Rebellion, All Rights Reserved.
//
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifdef ASURA_USE_VIDEO_TO_TEXTURE_SYSTEM

#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Entity/FMVController/Asura_FMVController_Messages.h"
#include "Entity/FMVController/Asura_ServerEntity_FMVController.h"
#include "Entity/FMVController/Asura_ServerEntity_FMVSpeaker.h"
#include "FMV/Asura_VideoToTexture.h"
#include "Network/Asura_Message.h"

#ifdef ASURA_TOOLS
#include "Tools_System.h"
#endif

Asura_Hashed_List< Asura_ServerEntity_FMVSpeaker > Asura_ServerEntity_FMVSpeaker::s_xList;

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

Asura_ServerEntity_FMVSpeaker::Asura_ServerEntity_FMVSpeaker(Asura_Guid uGuid)
: PARENT(uGuid)
, m_fInnerRange(0.5f)
, m_fOuterRange(1.5f)
, m_xLinkedControllerGuids(GuidCompareFunction)
{
	Classification = AsuraEntityClass_FMVSpeaker;
	s_xList.AddToList( this );
}

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

Asura_ServerEntity_FMVSpeaker::~Asura_ServerEntity_FMVSpeaker()
{
	Asura_TemplateTree_ConstIterator<Asura_Guid, Asura_Guid> xIterator(m_xLinkedControllerGuids);

	// Tell all linked Controllers to remove their references
	while(!xIterator.Done())
	{
		const Asura_Guid* puControllerGuid = xIterator.GetCurrent();

		if (puControllerGuid)
		{
			// Check the controller actually exists
			Asura_ServerEntity_FMVController* pxController = Asura_ServerEntity_FMVController::FindEntity(*puControllerGuid);
			if(pxController)
			{
				pxController->RemoveLinkedSpeaker(GetGuid());
			}
		}

		xIterator.Next();
	}
	s_xList.RemoveFromList( this );
}

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

void Asura_ServerEntity_FMVSpeaker::CreateFromChunkStream( Asura_Guid uGuid, Asura_Chunk_Stream &xStream )
{
	Asura_ServerEntity_FMVSpeaker* pxNew = new Asura_ServerEntity_FMVSpeaker(uGuid);
	if (pxNew)
	{
		pxNew->ReadFromChunkStream(xStream);
	}
}

////////////////////////////////////////////////////////////////////////////////
// WriteToChunkStream
////////////////////////////////////////////////////////////////////////////////

void Asura_ServerEntity_FMVSpeaker::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	// Version
	xStream << static_cast<int>( CURRENT_CHUNK_VERSION );

	PARENT::WriteToChunkStream(xStream);

	//
	// Write our data...
	//

	xStream << m_fInnerRange;
	xStream << m_fOuterRange;

	xStream << m_xLinkedControllerGuids.GetNumberOfNodes();

	Asura_TemplateTree_ConstIterator<Asura_Guid, Asura_Guid> xIterator(m_xLinkedControllerGuids);

	while(!xIterator.Done())
	{
		const Asura_Guid* puControllerGuid = xIterator.GetCurrent();

		if (puControllerGuid)
		{
			// Check the controller actually exists
			Asura_ServerEntity_FMVController* pxController = Asura_ServerEntity_FMVController::FindEntity(*puControllerGuid);
			if(pxController)
			{
				xStream << *puControllerGuid;
			}
			else
			{
				Asura_Assertf(false, ("FMV Speaker linked to non-existent Controller Guid [%d]", *puControllerGuid));
			}
		}

		xIterator.Next();
	}
}

////////////////////////////////////////////////////////////////////////////////
// ReadFromChunkStream
// Must cope with all versions up to CURRENT_CHUNK_VERSION (be backwards compatible)
////////////////////////////////////////////////////////////////////////////////

void Asura_ServerEntity_FMVSpeaker::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	// Version.
	int iVersion;
	xStream >> iVersion;

	// Parent data.
	PARENT::ReadFromChunkStream( xStream );    

	//
	// Read our data...
	//

	Asura_Assert((iVersion >= 0) && (iVersion <= CURRENT_CHUNK_VERSION), "Asura_ServerEntity_FMVSpeaker: Invalid chunk version");

	if ( iVersion >= 0 )
	{
		xStream >> m_fInnerRange;
		xStream >> m_fOuterRange;

		if ( iVersion >= 1 )
		{
			unsigned int uTotalGuids;
			xStream >> uTotalGuids;

			for(unsigned int uGuidCount = 0; uGuidCount < uTotalGuids; uGuidCount++)
			{
				unsigned int uThisGuid;
				xStream >> uThisGuid;
				AddLinkedController(uThisGuid);
			}
		}
	}
}

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

bool Asura_ServerEntity_FMVSpeaker::HandleMessage(const Asura_Message* pxMessage)
{
	if( IsDestroyed() ) { return true; } // ignore all further messages?

	if (pxMessage)
	{
		return PARENT::HandleMessage(pxMessage);
	}
	return false;
}

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

void Asura_ServerEntity_FMVSpeaker::AddLinkedController(Asura_Guid uGuid)
{
	Asura_Guid* pxGuid = m_xLinkedControllerGuids.AddNode(uGuid);
	Asura_Assertf(pxGuid, ("Unable to add FMV Controller Guid %d", uGuid));
	if (pxGuid)
	{
		*pxGuid = uGuid;
	}
}

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

void Asura_ServerEntity_FMVSpeaker::RemoveLinkedController(Asura_Guid uGuid)
{
	m_xLinkedControllerGuids.DeleteNode(uGuid);
}

#endif // ASURA_USE_VIDEO_TO_TEXTURE_SYSTEM
