/**
* FX Object
* @version: 01-29-2005
* @author Joseph 'Pcjoe' Florencio
*/
#ifndef FXOBJECT_H
#define FXOBJECT_H

class CFXEvent;
class CFXObject;
class CFXObjectSound;
class CFXObject3D;
class CFXObjectRender;
class CFXObjectMDL;
class CTimeline;
class CTimelineManager;
class CPathSystem;
class CMDLControl;
class CModelBlur;
// FMOD
extern FMODWrapper g_FMODWrapper;

#include "fxprecache.h"
#include "fxstorage.h"
#include "fxparse.h"
#include "fxcolor.h"
#include "fxdatapoint.h"
#include "fxtimeline.h"
#include "fxtimelinemanager.h"

/*
* BASE: FX Object
*/
class CFXObject
{
public:
	// Constructor
	CFXObject( CFXEvent *pEvent );

	// Can Use ( if the specified time is within the objects life time )
	virtual bool canUse( float flTime );

	// Can Remove (will always return false for fx tool)
	virtual bool canRemove( float flTime );

	// Think
	virtual void Think( float flTime );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObject"); }

	// clean up ( called on delete )
	virtual void cleanUp( void ) { }

	// Render Object
	virtual bool isRenderObject( void ) { return false; }

	// Camera Object
	virtual bool isCameraObject( void ) { return false; }

	/*
	* Accessors
	*/
	// Timeline Manager
	CTimelineManager *getTimelineManager( void ) { return &m_TimeManager; }

	// FX Event
	CFXEvent *getFXEvent( void ) { return m_pFXEvent; }
	void setFXEvent( CFXEvent *pFX ) { m_pFXEvent = pFX; }

	// Start Time
	void setStartTime( float flTime ) { m_flStartTime = flTime; }
	float getStartTime( void ) { return m_flStartTime; }

	// End Time
	void setEndTime( float flTime ) { m_flEndTime = flTime; }
	float getEndTime( void ) { return m_flEndTime; }

	// ID
	void setID( int idx ) { m_iID = idx; }
	int getID( void ) { return m_iID; }

	// Name
	void setName( std::string strName ) { m_strName = strName; }
	std::string getName( void ) { return m_strName; }

protected:
	// Timeline manager
	CTimelineManager	m_TimeManager;
	// FX Event we're linked to
	CFXEvent			*m_pFXEvent;

	std::string	m_strName;
	float		m_flStartTime;
	float		m_flEndTime;
	int			m_iID;
};

/*
* FX Object Trigger
*/
class CFXObjectTrigger : public CFXObject
{
public:
	// Constructor
	CFXObjectTrigger( CFXEvent *pEvent );
};

/*
* FX Object Sound
*/
class CFXObjectSound : public CFXObject
{
public:
	// Constructor
	CFXObjectSound( CFXEvent *pEvent );

	// clean up ( called on delete )
	virtual void cleanUp( void );

	// Think
	virtual void Think( float flTime );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObjectSound"); }

	// Reset Streams
	virtual void resetStreams( void );

	/*
	* Accessors
	*/
	// Stream 1
	void setStream1( FSOUND_STREAM *pStream ) { m_pStream1 = pStream; }
	FSOUND_STREAM *getStream1( void ) { return m_pStream1; }

	// Stream 2
	void setStream2( FSOUND_STREAM *pStream ) { m_pStream2 = pStream; }
	FSOUND_STREAM *getStream2( void ) { return m_pStream2; }

	// Channel 1
	void setChannel1( int iChannel ) { m_iChannel1 = iChannel; }
	int getChannel1( void ) { return m_iChannel1; }

	// Channel 2
	void setChannel2( int iChannel ) { m_iChannel2 = iChannel; }
	int getChannel2( void ) { return m_iChannel2; }

private:
	FSOUND_STREAM	*m_pStream1;
	FSOUND_STREAM	*m_pStream2;
	int				m_iChannel1;
	int				m_iChannel2;
};

/*
* FX Object 3D
*/
class CFXObject3D : public CFXObject
{
public:
	// Constructors
	CFXObject3D( CFXEvent *pEvent );

	// Think
	virtual void Think( float flTime );

	// Update Local Positional Data
	virtual void updateLocalPositionalData( void );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObject3D"); }

	// Channel Exist (channel index), return channel
	int channelExist( int iChannelIndex );

	// Create channel with specified channel index and channel
	void createChannel( int iChannelIndex, int iChannel );

	/*
	* Accessors
	*/
	// Get Path System
	CPathSystem	*getPathSystem( void );

	// Path
	void setPath( int iPath ) { m_iPath = iPath; }
	int getPath( void ) { return m_iPath; }

	// Distance
	void setDistance( float flDistance ) { m_flDistance = flDistance; }
	float getDistance( void ) { return m_flDistance; }

	// Position (Relitive to Base Position)
	void setPosition( vec3_t vecPos ) { m_vecPosition = vecPos; }
	vec3_t getPosition( void ) { return m_vecPosition; }

	// Rotation (Relitive to Base Angle)
	void setRotation( CQuaternion qRot ) { m_qRotation = qRot; }
	CQuaternion *getRotation( void ) { return &m_qRotation; }

	// Make local position/rotation final ( adjust to base angles, and add base position )
	vec3_t makePosFinal( vec3_t vecPos );
	CQuaternion makeAngFinal( CQuaternion qAngle );

	// Get Channels
	std::map<int,int> *getChannels( void ) { return &m_Channels; }

protected:
	int			m_iPath;
	float		m_flDistance;
	vec3_t		m_vecPosition;
	CQuaternion	m_qRotation;
	std::map<int,int>	m_Channels;
};

/*
* FX Object Render
*/
class CFXObjectRender : public CFXObject3D
{
public:
	// Constructor
	CFXObjectRender( CFXEvent *pEvent );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObjectRender"); }

	// Render
	virtual void Render( void ) { }

	// Render Object
	virtual bool isRenderObject( void ) { return true; }

	/*
	* Accessors
	*/
	// Size
	void setSize( float flSize ) { m_flSize = flSize; }
	float getSize( void ) { return m_flSize; }

	// Alpha
	void setAlpha( float flAlpha ) { m_flAlpha = flAlpha; }
	float getAlpha( void ) { return m_flAlpha; }

	// Color
	CFXColor *getColor( void ) { return &m_Color; }

	// Can Render
	void setRenderFlag( bool render ) { m_bRenderFlag = render; }
	bool canRender( void ) { return m_bRenderFlag; }

	// Render Mode
	void setRenderMode( int iMode ) { m_iRenderMode = iMode; }
	int getRenderMode( void ) { return m_iRenderMode; }

protected:
	bool		m_bRenderFlag;
	float		m_flSize;
	float		m_flAlpha;
	int			m_iRenderMode;
	CFXColor	m_Color;
};

/*
* FX Object Sprite
*/
class CFXObjectSprite : public CFXObjectRender
{
public:
	// Constructor
	CFXObjectSprite( CFXEvent *pEvent );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Render
	virtual void Render( void );

	/*
	* Accessors
	*/
};

/*
* FX Object Particle System
*/
class CFXObjectParticle : public CFXObjectRender
{
public:
	// Constructor
	CFXObjectParticle( CFXEvent *pEvent );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Render
	virtual void Render( void );

	/*
	* Accessors
	*/
};

/*
* FX Object MDL
*/
class CFXObjectMDL : public CFXObjectRender
{
public:
	// Constructor
	CFXObjectMDL( CFXEvent *pEvent );

	// Update Local Positional Data
	virtual void updateLocalPositionalData( void );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObjectMDL"); }

	// Setup Model ( attach to existing model )
	virtual void setupModel( int idx );

	// Setup Model ( create new temp entity
	virtual void setupModel( std::string strModel );

	// clean up ( called on delete )
	virtual void cleanUp( void );

	/*
	* Accessors
	*/
	// Model Control
	void setModelControl( CMDLControl *pCtrl ) { m_pModelControl = pCtrl; }
	CMDLControl *getModelControl( void ) { return m_pModelControl; }

	// Temp Entity
	void setTempEntity( TEMPENTITY *pEnt ) { m_pTempEntity = pEnt; }
	TEMPENTITY *getTempEntity( void ) { return m_pTempEntity; }

	// Model Blur
	void setModelBlur( CModelBlur *pBlur ) { m_pModelBlur = pBlur; }
	CModelBlur *getModelBlur( void ) { return m_pModelBlur; }

	// Index
	void setIndex( int idx ) { m_iIndex = idx; }
	int getIndex( void ) { return m_iIndex; }

	// Model
	void setModelName( std::string strName ) { m_strModelName = strName; }
	std::string getModelName( void ) { return m_strModelName; }
protected:
	CMDLControl	*m_pModelControl;
	TEMPENTITY	*m_pTempEntity;
	CModelBlur	*m_pModelBlur;
	int			m_iIndex;
	std::string m_strModelName;
};

/*
* FX Object WRL
*/
class CFXObjectWRL : public CFXObjectRender
{
public:
	// Constructor
	CFXObjectWRL( CFXEvent *pEvent );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObjectWRL"); }

	// update model data ( find model/texture using string data )
	void updateModelData( void );

	// Render
	virtual void Render( void );

	/*
	* Accessors
	*/

	// Model
	void setModelName( std::string strName ) { m_strModelName = strName; }
	void setModel( VRMLData *vrml ) { m_VRMLData = vrml; }
	std::string getModelName( void ) { return m_strModelName; }
	VRMLData *getModel( void ) { return m_VRMLData; }

	// Texture
	void setTextureName( std::string strName ) { m_strTextureName = strName; }
	void setTexture( HSPRITE *spr ) { m_hsprSprite = spr; }
	std::string getTextureName( void ) { return m_strTextureName; }
	HSPRITE *getTexture( void ) { return m_hsprSprite; }

protected:
	std::string	m_strModelName;
	std::string m_strTextureName;
	VRMLData	*m_VRMLData;
	HSPRITE		*m_hsprSprite;
};

/*
* FX Object Camera
*/
class CFXObjectCamera : public CFXObjectWRL
{
public:
	// Constructor
	CFXObjectCamera( CFXEvent *pEvent );

	// Can Use ( specified life span, and it's owned by the local user )
	virtual bool canUse( float flTime );

	// Add timeline(s)
	virtual void setupTimelines( void );

	// Get Type
	virtual std::string getType( void ) { return std::string("CFXObjectCamera"); }

	// Render
	virtual void Render( void );

	// Camera Object
	virtual bool isCameraObject( void ) { return true; }
};

#endif