/**
* FX System
* @version: 02-28-2005
* @author Joseph 'Pcjoe' Florencio
*/

#include "fxsys.h"
CFXSystem	g_FXSystem;
extern cvar_t *cl_fxscript_debug;

// Constructor/Destructor
CFXSystem::CFXSystem()
{	Reset();
}

CFXSystem::~CFXSystem()
{	Reset();
}

// Reset
void CFXSystem::Reset( void )
{	// Clear out events
	std::list<CFXEvent*>::iterator iterRemove = getEventList().begin();
	while(iterRemove != getEventList().end())
	{	iterRemove = removeEvent(iterRemove);
	}
	getEventList().clear();

	// Reset variables
	setDeveloperEventTime(0);
	setUsingCamera(false);
	setCameraPosition(vec3_t(0,0,0));
	setCameraAngle(vec3_t(0,0,0));
	resetDeveloperEvent();
}

// Think
void CFXSystem::Think( void )
{	// Reset camera usage every frame
	setUsingCamera(false);
	std::list<CFXEvent*>::iterator iterCurrent = getEventList().begin();
	while(iterCurrent != getEventList().end())
	{	CFXEvent *pEvent = (*iterCurrent);
		// Run off seperate time if event is in developer mode
		if(pEvent->isDeveloperEvent())
		{	pEvent->Think(pEvent->getStartTime()+getDeveloperEventTime());
			if(getDeveloperEvent() == NULL)
			{	setDeveloperEvent(*iterCurrent);
			}
		}
		// Run regular time
		else
		{	// Delete if too old and isn't set to loop
			if((pEvent->getEndTime() < gEngfuncs.GetClientTime()) && !(*iterCurrent)->isLooping())
			{	iterCurrent = removeEvent(iterCurrent);
				continue;
			}
			// Run normal think
			pEvent->Think(gEngfuncs.GetClientTime());
		}
		// Check to see if this event has a camera
		CFXObjectCamera *pCam = pEvent->getCameraObject();
		if(pCam && pCam->canUse(pEvent->getTime()-pEvent->getStartTime()))
		{	setCameraPosition(pCam->getPosition());
			setCameraAngle(pCam->makeAngFinal(*pCam->getRotation()).QuaternionToEuler());
			setUsingCamera(true);
		}
		
		iterCurrent++;
	}
}

// Render
void CFXSystem::Render( void )
{	bool bDebug = cl_fxscript_debug->value ? true : false;

	std::list<CFXEvent*>::iterator iterCurrent;
	ForEachIn(iterCurrent,getEventList())
	{	// Render object
		(*iterCurrent)->Render();

		// Render paths while in debug
		if(bDebug)
			(*iterCurrent)->getPathSystem()->RenderPaths();
	}
}

// Set Developer Event
void CFXSystem::setDeveloperEvent( CFXEvent* pDev )
{	if(pDev == NULL)
	{	// Remove developer tag
		if(getDeveloperEvent() != NULL)
		{	pDev->setDeveloperEvent(false);
		}
		resetDeveloperEvent();
		return;
	}
	// Set new developer event
	pDev->setDeveloperEvent(true);
	m_pDeveloperEvent = pDev;
}

// Reset Developer Event
void CFXSystem::resetDeveloperEvent( void )
{	m_pDeveloperEvent = NULL;
}

// Add Event
void CFXSystem::addEvent( CFXEvent *pEvent )
{	getEventList().push_back(pEvent);
}

// Remove Event
std::list<CFXEvent*>::iterator CFXSystem::removeEvent( std::list<CFXEvent*>::iterator iterRemove )
{	delete (*iterRemove);
	return getEventList().erase(iterRemove);
}

// Remove Event
std::list<CFXEvent*>::iterator CFXSystem::removeEvent( CFXEvent* pRemove )
{	std::list<CFXEvent*>::iterator iterRemove;
	for(iterRemove = getEventList().begin(); iterRemove != getEventList().end(); iterRemove++)
	{	if(*iterRemove == pRemove)
		{	delete pRemove;
			return getEventList().erase(iterRemove);
		}
	}
	return getEventList().end();
}