#ifndef _KVI_EVENT_H_
#define _KVI_EVENT_H_

//
//   File : kvi_event.h
//   Creation date : Thu Aug 17 2000 13:59:12 by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
//
//   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 opinion) 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. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#include "kvi_settings.h"

#include "kvi_string.h"
#include "kvi_list.h"
#include <qasciidict.h>

// Application
#define KviEvent_OnKVIrcStartup                  0
#define KviEvent_OnKVIrcShutdown                 1
// Irc Context
#define KviEvent_OnIrcContextCreated             2
#define KviEvent_OnIrcContextDestroyed           3
// Irc connection
#define KviEvent_OnIrcConnectionEstabilished     4
#define KviEvent_OnIrcConnectionTerminated       5
// Login complete
#define KviEvent_OnIrc                           6
// Channel userlist clicks
#define KviEvent_OnChannelNickPopupRequest          7
#define KviEvent_OnChannelNickDefaultActionRequest  8
// Frame window
#define KviEvent_OnFrameWindowCreated               9
#define KviEvent_OnFrameWindowDestroyed             10
// Text view
#define KviEvent_OnChannelPopupRequest              11
#define KviEvent_OnConsolePopupRequest              12
#define KviEvent_OnQueryPopupRequest                13

#define KviEvent_OnChannelSync                   14

#define KviEvent_OnUrl                           15

#define KviEvent_OnWindowPopupRequest            16

#define KviEvent_OnHostLinkPopupRequest          17
#define KviEvent_OnUrlLinkPopupRequest           18
#define KviEvent_OnServerLinkPopupRequest        19
#define KviEvent_OnChannelLinkPopupRequest       20
#define KviEvent_OnNickLinkPopupRequest          21
// Query nick clicks
#define KviEvent_OnQueryNickPopupRequest         22
#define KviEvent_OnQueryNickDefaultActionRequest 23

#define KviEvent_OnNickLinkDefaultActionRequest  24
#define KviEvent_OnTextViewDoubleClicked            25

#define KviEvent_OnNotifyListDefaultActionRequest 26
#define KviEvent_OnNotifyListPopupRequest 27

#define KviEvent_OnPing 28

#define KviEvent_OnMeJoin 29
#define KviEvent_OnJoin 30

#define KviEvent_OnTopic 31

#define KviEvent_OnMePart 32
#define KviEvent_OnPart 33

#define KviEvent_OnQuit 34

#define KviEvent_OnUserMode 35

#define KviEvent_OnMeKick 36
#define KviEvent_OnKick 37

#define KviEvent_OnMeAway 38
#define KviEvent_OnMeBack 39

#define KviEvent_OnChannelWindowCreated 40
#define KviEvent_OnQueryWindowCreated 41
#define KviEvent_OnBan 42
#define KviEvent_OnUnban 43
#define KviEvent_OnMeBan 44
#define KviEvent_OnMeUnban 45
#define KviEvent_OnBanException 46
#define KviEvent_OnBanExceptionRemove 47
#define KviEvent_OnMeBanException 48
#define KviEvent_OnMeBanExceptionRemove 49
#define KviEvent_OnOp 50
#define KviEvent_OnDeOp 51
#define KviEvent_OnMeOp 52
#define KviEvent_OnMeDeOp 53
#define KviEvent_OnLimitSet 54
#define KviEvent_OnLimitUnset 55
#define KviEvent_OnKeySet 56
#define KviEvent_OnKeyUnset 57
#define KviEvent_OnInvite 58
#define KviEvent_OnChannelMessage 59
#define KviEvent_OnQueryMessage 60
#define KviEvent_OnVoice 61
#define KviEvent_OnDeVoice 62
#define KviEvent_OnMeVoice 63
#define KviEvent_OnMeDeVoice 64
#define KviEvent_OnNickChange 65
#define KviEvent_OnMeNickChange 66
#define KviEvent_OnCtcpRequest 67
#define KviEvent_OnCtcpReply 68
#define KviEvent_OnUnhandledLiteral 69
#define KviEvent_OnMeHalfOp 70
#define KviEvent_OnMeDeHalfOp 71
#define KviEvent_OnHalfOp 72
#define KviEvent_OnDeHalfOp 73
#define KviEvent_OnInviteException 74
#define KviEvent_OnInviteExceptionRemove 75
#define KviEvent_OnMeInviteException 76
#define KviEvent_OnMeInviteExceptionRemove 77
#define KviEvent_OnAction 78
#define KviEvent_OnCtcpFlood 79
#define KviEvent_OnChannelNotice 80
#define KviEvent_OnServerNotice 81
#define KviEvent_OnDCCChatWindowCreated 82
#define KviEvent_OnDCCChatConnectionInProgress 83
#define KviEvent_OnDCCChatConnected 84
#define KviEvent_OnDCCChatMessage 85
#define KviEvent_OnDCCChatError 86
#define KviEvent_OnDCCChatDisconnected 87
#define KviEvent_OnDCCChatWindowClosing 88
#define KviEvent_OnAccelKeyPressed 89
#define KviEvent_OnHighlight 90
#define KviEvent_OnWindowActivated 91
#define KviEvent_OnNotifyOnLine 92
#define KviEvent_OnNotifyOffLine 93
#define KviEvent_OnPong 94
#define KviEvent_OnLagAlarmTimeUp 95
#define KviEvent_OnLagAlarmTimeDown 96
#define KviEvent_OnLagCheck 97

#define KVI_NUM_SCRIPT_EVENTS 98

// FIXME: #warning "Query user list clicks"
// FIXME: #warning "Notify list clicks"
// FIXME: #warning "Dcc user list clicks (other user list clicks)"
// FIXME: #warning "OnIdle : when the user stops to type on the keyboard"



class KviModule;
class KviEventHandler;
class KviScriptEventHandler;
class KviModuleEventHandler;

typedef KviPtrList<KviEventHandler> KviEventHandlerList;

typedef struct _KviEventStruct
{
	const char * szName;
	const char * szParams;
	KviEventHandlerList * handlers;
} KviEventStruct;


class KVIRC_API KviEventManager
{
	friend class KviUserParser;
	friend class KviModule;
public:
	KviEventManager();
	~KviEventManager();
protected:
	static KviEventStruct             m_eventTable[KVI_NUM_SCRIPT_EVENTS];
	KviEventHandlerList *             m_rawNumericEventTable[1000];
public:
	void load(const char * filename);
	void save(const char * filename);

	void loadRaw(const char * filename);
	void saveRaw(const char * filename);

	void clear();
	void clearScriptHandlers();
	void clearRawScriptHandlers();

	const char * eventName(int index){ return m_eventTable[index].szName; };
	const char * eventParams(int index){ return m_eventTable[index].szParams; };

	bool hasEventHandlers(int index){ return (m_eventTable[index].handlers); };
	bool hasRawEventHandlers(int index){ return (m_rawNumericEventTable[index]); };
	// unused ?
	KviEventHandlerList * handlers(int index){ return m_eventTable[index].handlers; };
	KviEventHandlerList * rawNumericHandlers(int index){ return m_rawNumericEventTable[index]; };

	bool registerScriptHandler(const char * evName,const char * hndName,const char * code,bool bEnabled = true);
	bool unregisterScriptHandler(const char * evName,const char * hndName);
	bool enableScriptHandler(const char * evName,const char * hndName,bool bEnable);
	const char * lookupScriptHandlerCode(const char * evName,const char * hndName);

	bool registerRawNumericScriptHandler(int idx,const char * hndName,const char * code,bool bEnabled = true);
	bool unregisterRawNumericScriptHandler(int idx,const char * hndName);
	bool enableRawNumericScriptHandler(int idx,const char * hndName,bool bEnable);
	const char * lookupRawNumericScriptHandlerCode(int idx,const char * hndName);

protected: // KviModule
	void registerModuleHandler(int evIdx,KviModuleEventHandler * h);
	void unregisterModuleHandler(int evIdx,KviModule * m);
	void registerRawNumericModuleHandler(int evIdx,KviModuleEventHandler * h);
	void unregisterRawNumericModuleHandler(int evIdx,KviModule * m);
	void unregisterAllModuleHandlers(KviModule * m);
protected:

	void clearScriptHandlers(KviEventHandlerList * l);

	int lookupEventByName(const char * n);

	KviScriptEventHandler * lookupScriptEventHandler(int evIdx,const char * hndName);
	KviScriptEventHandler * lookupRawNumericScriptEventHandler(int evIdx,const char * hndName);
};

extern KVIRC_API KviEventManager * g_pEventManager;

#ifndef _KVI_EVENT_CPP_

	#include "kvi_uparser.h"

	// This is a quick macro... can't propagate the return value..so it is useless when we
	// have to handle the 'halt' command

	#define TRIGGER_EVENT(__idx,__wnd) \
		if(g_pEventManager->hasEventHandlers(__idx))g_pUserParser->triggerEvent(__idx,__wnd,0)

	// This one propagates the return value of triggerEvent (returns TRUE if halt was called!)

	#define TRIGGER_EVENT_RETVALUE(__idx,__wnd) \
		(g_pEventManager->hasEventHandlers(__idx) ? g_pUserParser->triggerEvent(__idx,__wnd,0) : false)


	#define TRIGGER_EVENT_1PARAM(__idx,__wnd,__p1) \
		if(g_pEventManager->hasEventHandlers(__idx))g_pUserParser->triggerEvent(__idx,__wnd, \
			new KviParameterList(new KviStr(__p1)))

	#define TRIGGER_EVENT_1PARAM_NONEW(__idx,__wnd,__p1) \
		if(g_pEventManager->hasEventHandlers(__idx))g_pUserParser->triggerEvent(__idx,__wnd, \
			new KviParameterList(__p1))

	#define TRIGGER_EVENT_1PARAM_RETVALUE(__idx,__wnd,__param) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd,new KviParameterList(new KviStr(__param))) : false)

	#define TRIGGER_EVENT_2PARAM_RETVALUE(__idx,__wnd,__p1,__p2) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd, \
				new KviParameterList(new KviStr(__p1),new KviStr(__p2))) : \
			false)

	#define TRIGGER_EVENT_3PARAM_RETVALUE(__idx,__wnd,__p1,__p2,__p3) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd, \
				new KviParameterList(new KviStr(__p1),new KviStr(__p2),new KviStr(__p3))) : \
			false)

	#define TRIGGER_EVENT_4PARAM_RETVALUE(__idx,__wnd,__p1,__p2,__p3,__p4) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd, \
				new KviParameterList(new KviStr(__p1),new KviStr(__p2), \
					new KviStr(__p3),new KviStr(__p4))) : \
			false)

	#define TRIGGER_EVENT_5PARAM_RETVALUE(__idx,__wnd,__p1,__p2,__p3,__p4,__p5) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd, \
				new KviParameterList(new KviStr(__p1),new KviStr(__p2), \
					new KviStr(__p3),new KviStr(__p4),new KviStr(__p5))) : \
			false)

	#define TRIGGER_EVENT_6PARAM_RETVALUE(__idx,__wnd,__p1,__p2,__p3,__p4,__p5,__p6) \
		(g_pEventManager->hasEventHandlers(__idx) ? \
			g_pUserParser->triggerEvent(__idx,__wnd, \
				new KviParameterList(new KviStr(__p1),new KviStr(__p2), \
					new KviStr(__p3),new KviStr(__p4),new KviStr(__p5),new KviStr(__p6))) : \
			false)


#endif

#endif //_KVI_EVENT_H_
