/******************************************************************************
 *    dh2.h
 *
 *    This file is part of Dark Hook 2
 *    Copyright (C) 2005-2009 Tom N Harris <telliamed@whoopdedo.org>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *****************************************************************************/
/**********************
 * DarkHook2 
 */

#ifndef DH2_H
#define DH2_H

#if _MSC_VER > 1000
#pragma once
#endif

#include <lg/objstd.h>
#include <lg/iiddef.h>
#include <lg/types.h>
#include <lg/scrmanagers.h>
#include <lg/properties.h>
#include <lg/links.h>
#include <lg/objects.h>

#include <map>
#include <list>

#include "darkhook.h"
#include "objprop.h"


class cDH2ScriptService : public IDarkHookScriptService
{
public:
	virtual HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
	virtual ULONG __stdcall AddRef(void);
	virtual ULONG __stdcall Release(void);

	virtual void __stdcall Init(void);
	virtual void __stdcall End(void);

	virtual BOOL __stdcall InstallPropHook(int iAgent, eDHRegisterFlags eFlags, const char * pszProp, int iObj);
	virtual void __stdcall UninstallPropHook(int iAgent, const char * pszProp, int iObj);

	virtual BOOL __stdcall InstallRelHook(int iAgent, eDHRegisterFlags eFlags, const char * pszRel, int iObj);
	virtual void __stdcall UninstallRelHook(int iAgent, const char * pszRel, int iObj);

	virtual BOOL __stdcall InstallObjHook(int iAgent, eDHRegisterFlags eFlags, int iObj);
	virtual void __stdcall UninstallObjHook(int iAgent, int iObj);

	virtual BOOL __stdcall InstallHierarchyHook(int iAgent, eDHRegisterFlags eFlags, int iObj);
	virtual void __stdcall UninstallHierarchyHook(int iAgent, int iObj);

	cDH2ScriptService(IUnknown* pIFace);
	virtual ~cDH2ScriptService();

	static bool sm_initialized;

private:
	ULONG m_iRef;

	IScriptMan* m_pScriptMan;
	IPropertyManager* m_pPropMan;
	ILinkManager* m_pLinkMan;
	IObjectSystem* m_pObjMan;
	ITraitManager* m_pTraitMan;
	ISimManager* m_pSimMan;

	static void __stdcall PropertyListener(sPropertyListenMsg* pPropMsg, PropListenerData hData);
	static void __stdcall RelationListener(sRelationListenMsg* pRelMsg, void* pData);
	static void __cdecl ObjectListener(int iObjId, unsigned long uEvent, void* pData);
	static void __stdcall HierarchyListener(const sHierarchyMsg* pTraitMsg, void* pData);
	static int __cdecl SimListener(const sDispatchMsg* pSimMsg, const sDispatchListenerDesc* pDesc);

	static sDispatchListenerDesc sm_simlistenerdesc;

	static std::map<int,PropListenerHandle> sm_prophookhandles;
	static std::map<int,bool> sm_relhookactive;
	static int 	 sm_objhookhandle;
	static bool	 sm_traithookactive;

	typedef std::list<std::pair<int,eDHRegisterFlags> >  objlist;
	std::map<objprop,objlist>     m_proptree;
	std::map<objprop,objlist>     m_reltree;
	std::map<int,objlist>         m_objtree;
	std::map<int,objlist>         m_traittree;

	void HandleProperty(sPropertyListenMsg* pPropMsg, PropListenerData pData);
	void HandleRelation(sRelationListenMsg* pRelMsg, void* pData);
	void HandleObject(int iObjId, unsigned long uEvent, void* pData);
	void HandleHierarchy(const sHierarchyMsg* pTraitMsg, void* pData);

	void DoPropertyNotify(int iAgent, eDHRegisterFlags eFlags, unsigned int uEvent, const char* pszName, int iObjId, void* pData);
	void DoRelationNotify(int iAgent, eDHRegisterFlags eFlags, unsigned int uEvent, const char* pszName, long lLinkId, int iLinkSource, int iLinkDest, IRelation* pRel);
	void DoObjectNotify(int iAgent, eDHRegisterFlags eFlags, unsigned int uEvent, int iObjId);
	void DoHierarchyNotify(int iAgent, eDHRegisterFlags eFlags, unsigned int uEvent, int iObjId, int iSubjId);

	void Reset(void);
};

#endif // DH2_H
