#pragma once

class Script;
class TESForm;
class TESObjectREFR;

namespace EventManager
{
	enum eEventID {
		kEventID_OnHit,
		kEventID_OnHitWith,
		kEventID_OnMagicEffectHit,
		kEventID_OnActorEquip,
		kEventID_OnDeath,
		kEventID_OnMurder,
		kEventID_OnKnockout,
		kEventID_OnActorUnequip,
		kEventID_OnAlarm_Trespass,
		kEventID_OnAlarm_Steal,
		kEventID_OnAlarm_Attack,
		kEventID_OnAlarm_Pickpocket,
		kEventID_OnAlarm_Murder,
		kEventID_OnPackageChange,
		kEventID_OnPackageStart,
		kEventID_OnPackageDone,
		kEventID_OnStartCombat,
		kEventID_OnActivate,

		kEventID_GameEventMAX,

		kEventID_LoadGame = kEventID_GameEventMAX,
		kEventID_SaveGame,
		kEventID_ExitGame,
		kEventID_ExitToMainMenu,
		kEventID_QQQ,
		kEventID_PostLoadGame,

		kEventID_MAX,
	};

	struct EventCallback
	{
		EventCallback(Script* funcScript, TESObjectREFR* sourceFilter = NULL, TESForm* objectFilter = NULL)
			: script(funcScript), source(sourceFilter), object(objectFilter), flags(0) { }
		~EventCallback() { }

		
		enum {
			kFlag_Removed		= 1 << 0,		// set when RemoveEventHandler called while handler is in use
			kFlag_InUse			= 1 << 1,		// is in use by HandleEvent (so removing it would invalidate an iterator)
		};

		Script			* script;
		TESObjectREFR	* source;
		TESForm			* object;
		UInt8			flags;

		bool IsInUse() const { return flags & kFlag_InUse ? true : false; }
		bool IsRemoved() const { return flags & kFlag_Removed ? true : false; }
		void SetInUse(bool bSet) { flags = bSet ? flags | kFlag_InUse : flags & ~kFlag_InUse; }
		void SetRemoved(bool bSet) { flags = bSet ? flags | kFlag_Removed : flags & ~kFlag_Removed; }
	};

	bool SetHandler(const char* id, EventCallback& handler);
	bool RemoveHandler(const char* id, EventCallback& handler);
	bool RemoveHandler(const char* id, Script* fnScript);

	void __stdcall HandleGameEvent(UInt32 eventMask, TESObjectREFR* source, TESForm* object);
	void HandleOBSEMessage(UInt32 msgID, void* data);

	const char* GetCurrentEventName();

	void Tick();
};
