//
// Asura_ServerEntity_LogicTrigger.h
//
// Created by Richard Rice - 07/10/2004
// 
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_SERVERENTITY_LOGICTRIGGER_H__
#define __ASURA_SERVERENTITY_LOGICTRIGGER_H__

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

#include "Core/Asura_Hash.h"
#include "Core/Asura_HashedList.h"

struct Asura_LogicTriggerInput
{
	void SetDefaultValues();

	Asura_Hash_ID m_uHashID;//id generated from input name
	union
	{
		unsigned int m_uFlags;
		struct 
		{
			unsigned int m_bActive : 1,
						   m_uSpareBits : 31;
		};
	};

	#ifdef ASURA_TOOLS
	Asura_String m_xName;
	#endif
};

struct Asura_LogicTrigger_Chunk
{
	unsigned short m_usMessageBlockOn;//message block to send when switched on
	unsigned short m_usMessageBlockOff;//message block to send when switched off
};


enum Asura_LogicTriggerType
{
	ASURA_LOGICTRIGGER_AND,
	ASURA_LOGICTRIGGER_OR,
	ASURA_LOGICTRIGGER_XOR,
};

#define ASURA_LOGICTRIGGERFLAG_TRIGGER_ON_STATE_CHANGE 0x00000001 //Causes the logic trigger to send its messages whenever the state changes.


class Asura_ServerEntity_LogicTrigger : public Asura_ServerEntity_Activatable
{
	typedef Asura_ServerEntity_Activatable PARENT;

	public :
		Asura_ServerEntity_LogicTrigger();

		//constructor from load
		Asura_ServerEntity_LogicTrigger(Asura_Guid uGuid);

		static void Create( Asura_Guid uGuid, Asura_Chunk_Stream& xStream );


		virtual ~Asura_ServerEntity_LogicTrigger();
	
		virtual bool HandleMessage(const Asura_Message* pxMessage);

		unsigned int GetNumberOfInputs() const {return m_uNumberOfInputs;}

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

		#ifdef ASURA_TOOLS
		//gets a more detailed description of input triggers
		static const char* GetMessageDescription(const struct Asura_StaticMessage* pxMessage);
		Asura_String GetInputName(u_int uIndex) { return m_pxInputs[uIndex].m_xName; }
		#endif


		#ifdef ASURA_SUPPORT_ENTITYWATCH
		virtual void DisplayEntityWatchText();
		#endif

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

	protected :

		bool EvaluateState();

		enum
		{
			MESSAGE_BLOCK_ON,
			MESSAGE_BLOCK_OFF,
			NUM_MESSAGE_BLOCKS,
		};

		//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


		unsigned int m_uNumberOfInputs;
		Asura_LogicTriggerInput* m_pxInputs;

		unsigned int m_uType;//trigger type , taken from enumeration

		// IMPORTANT - If adding to these message blocks - then also add to the enum above
		unsigned short m_usMessageBlockOn;//message block to send when switched on
		unsigned short m_usMessageBlockOff;//message block to send when switched off

		unsigned int m_uLogicFlags;
		
		friend class Tools_Entity_LogicTrigger_Object;

	public:
		static Asura_ServerEntity_LogicTrigger* FindEntity(Asura_Guid uGuid)
		{
			return s_xList.FindEntity(uGuid);
		}

		static const Asura_Hashed_List<Asura_ServerEntity_LogicTrigger>* GetList()
		{
			return &s_xList;
		}


	private:
		static Asura_Hashed_List<Asura_ServerEntity_LogicTrigger> s_xList;

};

//This message is saved out to static message system , so care needs to be taken about altering it
struct Asura_Message_LogicTrigger_Input 
{
	Asura_Hash_ID m_uInputHash;	
};


#endif //__ASURA_SERVERENTITY_LOGICTRIGGER_H__
