/*!
	@file
	@author		Georgiy Evmenov
	@date		08/2008
	@module
*/
#ifndef __MYGUI_DELEGATE_MANAGER_H__
#define __MYGUI_DELEGATE_MANAGER_H__

#include "MyGUI_Prerequest.h"
#include "MyGUI_Instance.h"
#include "MyGUI_Common.h"
#include "MyGUI_Widget.h"

namespace MyGUI
{

	#define DELEGATE_MANAGER_EVENT0(name) void name(MyGUI::WidgetPtr _sender){callDelegate(_sender, _sender->getUserString(#name), #name);}
	#define DELEGATE_MANAGER_EVENT1(name, param1) void name(MyGUI::WidgetPtr _sender, param1){callDelegate(_sender, _sender->getUserString(#name), #name);}
	#define DELEGATE_MANAGER_EVENT2(name, param1, param2) void name(MyGUI::WidgetPtr _sender, param1, param2){callDelegate(_sender, _sender->getUserString(#name), #name);}
	#define DELEGATE_MANAGER_EVENT3(name, param1, param2, param3) void name(MyGUI::WidgetPtr _sender, param1, param2, param3){callDelegate(_sender, _sender->getUserString(#name), #name);}
	#define DELEGATE_MANAGER_EVENT4(name, param1, param2, param3, param4) void name(MyGUI::WidgetPtr _sender, param1, param2, param3, param4){callDelegate(_sender, _sender->getUserString(#name), #name);}
		/*void eventName(MyGUI::WidgetPtr _sender, [parameters])
		{
			callDelegate(_sender, _sender->getUserString("eventName"), "eventName");
		}*/

	/**	Manager for handling delegates by names.
	*/
	class MYGUI_EXPORT DelegateManager
	{
		MYGUI_INSTANCE_HEADER(DelegateManager);
	public:
		typedef delegates::CDelegate3<WidgetPtr, const std::string&, const std::string&> HandleEvent;
		typedef std::map<std::string, HandleEvent> MapDelegate;
	public:
		void initialise();
		void shutdown();

		/** @example "Add new delegate for DelegateManager"
		@code
		MyGUI::DelegateManager::getInstance().addDelegate("delegate_name_1", MyGUI::newDelegate(your_func));
		MyGUI::DelegateManager::getInstance().addDelegate("delegate_name_2", MyGUI::newDelegate(your_static_method));
		MyGUI::DelegateManager::getInstance().addDelegate("delegate_name_3", MyGUI::newDelegate(your_class_ptr, &your_class_name::your_method_name));
		@endcode

		signature : void method(MyGUI::WidgetPtr _sender, const std::string & _key, const std::string & _event)
		*/
		void addDelegate(const std::string & _key, HandleEvent::IDelegate * _delegate);

		/** Remove delegate */
		void removeDelegate(const std::string & _key);
	private:
		void callDelegate(WidgetPtr _sender, const std::string & _key, const std::string & _event);
	public:
		DELEGATE_MANAGER_EVENT1(eventMouseLostFocus, MyGUI::WidgetPtr _new);
		DELEGATE_MANAGER_EVENT1(eventMouseSetFocus, MyGUI::WidgetPtr _new);
		DELEGATE_MANAGER_EVENT2(eventMouseDrag, int _left, int _top);
		DELEGATE_MANAGER_EVENT2(eventMouseMove, int _left, int _top);
		DELEGATE_MANAGER_EVENT1(eventMouseWheel, int _rel);
		DELEGATE_MANAGER_EVENT3(eventMouseButtonPressed, int _left, int _top, MyGUI::MouseButton _id);
		DELEGATE_MANAGER_EVENT3(eventMouseButtonReleased, int _left, int _top, MyGUI::MouseButton _id);
		DELEGATE_MANAGER_EVENT0(eventMouseButtonClick);
		DELEGATE_MANAGER_EVENT0(eventMouseButtonDoubleClick);


		///** Event : Widget lost keyboard focus.\n
		//	signature : void method(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr _new)\n
		//	@param _new widget with keyboard focus or nullptr
		//*/
		//EventInfo_WidgetWidget eventKeyLostFocus;

		///** Event : Widget got keyboard focus.\n
		//	signature : void method(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr _old)\n
		//	@param _old widget with keyboard focus or nullptr
		//*/
		//EventInfo_WidgetWidget eventKeySetFocus;

		///** Event : Key pressed.\n
		//	signature : void method(MyGUI::WidgetPtr _sender, MyGUI::KeyCode _key, MyGUI::Char _char)\n
		//	@param _key code
		//	@param _char of pressed symbol (for multilanguage applications)
		//*/
		//EventInfo_WidgetKeyCodeChar eventKeyButtonPressed;

		///** Event : Key released.\n
		//	signature : void method(MyGUI::WidgetPtr _sender, MyGUI::KeyCode _key)\n
		//	@param _key code
		//*/
		//EventInfo_WidgetKeyCode eventKeyButtonReleased;

		///** Event : Root widget changed mouse focus.\n
		//	info : this event sends only to root widget\n
		//	signature : void method(MyGUI::WidgetPtr _sender, bool _focus);
		//	@param _focus Is widget got mouse focus.
		//*/
		//EventInfo_WidgetBool  eventRootMouseChangeFocus;

		///** Event : Root widget changed keyboard focus.\n
		//	info : this event sends only to root widget\n
		//	signature : void method(MyGUI::WidgetPtr _sender, bool _focus);
		//	@param _focus Is widget got keyboard focus.
		//*/
		//EventInfo_WidgetBool eventRootKeyChangeFocus;

		///** Event : Extendeble event for special cases or plugins.\n
		//	signature : void method(MyGUI::WidgetPtr _sender, const std::string & _key, const std::string & _value);
		//*/
		///* event : общее расширяемое событие для плагинов или особых случаев*/
		///* signature : void method(MyGUI::WidgetPtr _sender, const std::string & _key, const std::string & _value);*/
		//EventInfo_WidgetStringString eventActionInfo;

		///* event : внутренний запрос на родителя и номера айтема, у любого виджета*/
		///* signature : void method(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr & _list, size_t & _index);*/
		//EventInfo_WidgetRefWidgetRefSizeT  requestGetContainer;

		///* event : внутреннее событие, невалидна информация для дропа*/
		///* signature : void method(MyGUI::WidgetPtr _sender);*/
		//EventInfo_WidgetVoid eventInvalideContainer;

		//// event : запрос на начало дропа
		//// signature : void method(MyGUI::WidgetPtr _sender, const MyGUI::ItemDropInfo& _info, bool & _result)
		//EventInfo_WidgetCItemDropInfoRefBoolRef eventStartDrop;

		//// event : запрос на дроп айтема
		//// signature : void method(MyGUI::WidgetPtr _sender, const MyGUI::ItemDropInfo& _info, bool & _result)
		//EventInfo_WidgetCItemDropInfoRefBoolRef eventRequestDrop;

		//// event : завершение дропа
		//// signature : void method(MyGUI::WidgetPtr _sender, const MyGUI::ItemDropInfo& _info, bool _result)
		//EventInfo_WidgetCItemDropInfoRefBool eventEndDrop;

		//// event : текущее состояние дропа
		//// signature : void method(MyGUI::WidgetPtr _sender, DropState _state)
		//EventInfo_WidgetDropState eventDropState;

		DELEGATE_MANAGER_EVENT1(eventToolTip, const MyGUI::ToolTipInfo & _info);

		MapDelegate mDelegates;
	};

} // namespace MyGUI

#endif // __MYGUI_DELEGATE_MANAGER_H__
