//////////////////////////////////////////////////////////////////////////////
//
// Asura_ServerEntity_TimelineTrigger.h
//
// Copyright (C) 2008 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifndef __ASURA_SERVERENTITY_TIMELINETRIGGER_H__
#define __ASURA_SERVERENTITY_TIMELINETRIGGER_H__ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Entity/Triggers/Asura_ServerEntity_Activatable.h"
#include "Core/Asura_Hash.h"
#ifdef ASURA_TOOLS
#include "Core/Asura_String.h"
#include "Entity/Asura_Entity_Classification.h"
#endif

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_Chunk_Stream;
struct Asura_TimelineTrigger_MessageBlock;

//Variation of time trigger , that has multiple message blocks to be triggered
//at different times.

#define ASURA_TIMELINETRIGGERFLAG_LOOP 0x00000001

//////////////////////////////////////////////////////////////////////////////
//
// Asura_ServerEntity_TimelineTrigger
//
//////////////////////////////////////////////////////////////////////////////

//data for single trigger/message in timeline
struct Asura_TimelineTrigger_MessageBlock
{
	void SetDefaultValues();

	Asura_Hash_ID m_uHashID;//generated from name
	float m_fTime;//trigger time in seconds

	unsigned short m_usMessageBlock;
	union
	{
		unsigned short m_usFlags;
		struct
		{
			unsigned short	m_bActive :1,
							m_usSpareBits:15;			
		};
	};

	#ifdef ASURA_TOOLS
	Asura_String m_xName;
	bool m_bSelected;//timer selected in tools
	#endif
};

class Asura_ServerEntity_TimelineTrigger : public Asura_ServerEntity_Activatable
{
public:
	Asura_ServerEntity_TimelineTrigger();
	Asura_ServerEntity_TimelineTrigger( const Asura_Guid uGuid );
	virtual ~Asura_ServerEntity_TimelineTrigger();

	virtual void Update();
	virtual bool HandleMessage(const Asura_Message* pxMessage);

	bool IsLooped() const {return m_uTimelineTriggerFlags & ASURA_TIMELINETRIGGERFLAG_LOOP;}

	#ifdef ASURA_TOOLS
	virtual void ApplyChangesForTemplateInstance(class Tools_EntityTemplateInstance* pxInstance);
	virtual bool CanBeIncludedInTemplate() const {return Classification == AsuraEntityClass_TimelineTrigger;}
	#endif

	unsigned int GetNumberOfMessageBlocks() const {return m_uNumberOfMessageBlocks;}
	void SetNumberOfMessageBlock(unsigned int uNumMessageBlocks) { m_uNumberOfMessageBlocks = uNumMessageBlocks; }
	const Asura_TimelineTrigger_MessageBlock* GetMessageBlocks() { return m_pxMessageBlocks; }

	#ifdef ASURA_TOOLS
	//gets a more detailed description of activate/deactiivate messages
	static const char* GetMessageDescription(const struct Asura_StaticMessage* pxMessage);
	#endif


	#ifdef ASURA_SUPPORT_ENTITYWATCH
	virtual void DisplayEntityWatchText();
	#endif

	#ifdef ASURA_TOOLS
	virtual bool SupportsCustomEvents() const { return true; }
	virtual int GetNumCustomEvents() const { return m_uNumberOfMessageBlocks; }
	virtual unsigned short* GetCustomEvent(int iIndex) { return &m_pxMessageBlocks[iIndex].m_usMessageBlock; }
	virtual void GetCustomEventName(int iEventIndex, Asura_String& xEventName);
	#endif

	static void CreateFromChunkStream( const Asura_Guid uGuid, Asura_Chunk_Stream& xStream );

protected:

	//virtual function overides for saving
	virtual	bool IsFilledFromChunkBuffer() const { return false; }
	virtual	void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
	virtual	void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;

	#ifdef ASURA_TOOLS
	int GetToolsDataSize() const;
	#endif

	//Sets the timer ,triggering any message blocks as needed
	void SetTimer(float fTimer);
	//Sets the trigger time for a message block , possibly causing it to be triggered
	void SetTriggerTime(u_int uOutput,float fTime);

	//triggers messages between the two times
	void TriggerMessages(float fStartTime,float fEndTime);

	float GetMaxTriggerTime() const;
	void InvalidateMaxTriggerTime() {m_fMaxTriggerTime = -1.0f;}


	unsigned int m_uNumberOfMessageBlocks;
	Asura_TimelineTrigger_MessageBlock* m_pxMessageBlocks;

	float m_fTimer;
	u_int m_uTimelineTriggerFlags;

	mutable float m_fMaxTriggerTime;
	
	friend class Tools_Entity_TimelineTrigger_Object;

	#ifdef ASURA_TOOLS
public:
	static Asura_ServerEntity_TimelineTrigger* FindEntity(Asura_Guid uGuid) { return s_xList.FindEntity(uGuid); }
	static const Asura_Hashed_List<Asura_ServerEntity_TimelineTrigger>* GetList() { return &s_xList; }

private:
	static Asura_Hashed_List<Asura_ServerEntity_TimelineTrigger> s_xList;
	#endif // ASURA_TOOLS

	enum { CURRENT_CHUNK_VERSION = 1000 };
};

//These messages are saved out to static message system , so care needs to be taken about altering them
struct Asura_Message_TimelineTrigger 
{
	Asura_Hash_ID m_uMessageHash;	
};

struct Asura_Message_TimelineTrigger_SetTriggerTime	: Asura_Message_TimelineTrigger
{
	float m_fTriggerTime;
};

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

#endif //__ASURA_SERVERENTITY_TIMELINETRIGGER_H__
