#include "../../Scene/Controller/RuController_MaterialTexture.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

ruRTTI_DEFINE_SUBCLASS(CRuController_MaterialTexture, IRuEntity_Controller)
ruHEAP_DEFINE_SUBCLASS(CRuController_MaterialTexture, "CRuController_MaterialTexture", "IRuEntity_Controller")
ruCLASSGUID_DEFINE(CRuController_MaterialTexture, 0xD677EE4E, 0xB03B4e50, 0x8CEE0025, 0xE5BB5B45)

// ************************************************************************************************************************************************************

CRuController_MaterialTexture::CRuController_MaterialTexture()
:	m_targetMaterial(NULL),
	m_curTextureIndex(0),
	m_frameRate(30.0f),
	m_tDelta(0.0f),
	m_targetChannel(ruTEXCHANNEL_INVALID)
{
	// Register as listener for self in order to handle the ruENTITYEVENT_ONDESTROY event.
	this->RegisterListener(this, NULL);
}

CRuController_MaterialTexture::~CRuController_MaterialTexture()
{
	// NOTE: Destruction of resources is done during the ruENTITYEVENT_ONDESTROY event.
}

BOOL CRuController_MaterialTexture::Update(REAL elapsedTime)
{
	if(m_enabled)
	{
		REAL frameTime = 1.0f / m_frameRate;

		m_tDelta += elapsedTime;

		INT32 increments = 0;
		while(m_tDelta >= frameTime)
		{
			++increments;
			m_tDelta -= frameTime;
		}

		if(m_textureList.Count() > 0)
		{
			m_curTextureIndex += increments;
			m_curTextureIndex %= m_textureList.Count();

			if(m_targetMaterial)
			{
				m_targetMaterial->SetTexture(m_targetChannel, m_textureList[m_curTextureIndex]);
			}

		}
	}

	// Chain update call to base controller class
	return IRuEntity_Controller::Update(elapsedTime);
}

IRuObject *CRuController_MaterialTexture::GetTarget()
{
	return m_targetMaterial;
}

BOOL CRuController_MaterialTexture::SetTarget(IRuObject *target)
{
	if(target->GetType().IsSubClassOf(IRuMaterial::Type))
	{
		m_targetMaterial = static_cast<IRuMaterial *>(target);

		return TRUE;
	}

	return FALSE;
}

void CRuController_MaterialTexture::SetTargetChannel(RuTextureChannel targetChannel)
{
	m_targetChannel = targetChannel;
}

BOOL CRuController_MaterialTexture::AddTexture(IRuBaseTexture *texture)
{
	if(texture)
	{
		m_textureList.Add(texture);
		texture->AddRef();

		return TRUE;
	}

	return FALSE;
}

BOOL CRuController_MaterialTexture::HandleEvent(CRuEntity *entity, INT32 eventID, INT32 eventParameter0, INT32 eventParameter1, const char *eventString, REAL eventDuration, void *userData)
{
	// Chain event handler to base class
	if(IRuEntity_Controller::HandleEvent(entity, eventID, eventParameter0, eventParameter1, eventString, eventDuration, userData) == TRUE)
	{
		return TRUE;
	}

	// Ensure that the broadcasting entity is the target entity for this controller or the controller itself
//	if(entity != m_targetEntity && entity != this)
	if(entity != this)
	{
		return FALSE;
	}

	// Handle event
	switch(eventID)
	{
		case ruENTITYEVENT_ONDESTROY:		// Target entity is being destroyed, unregister the controller
			{
				// Release all texture references
				for(INT32 i = 0; i < m_textureList.Count(); ++i)
				{
					ruSAFE_RELEASE(m_textureList[i]);
				}
			}

			break;
	}

	return FALSE;
}

// ************************************************************************************************************************************************************

#pragma managed
