#pragma once
#include "IInput.h"
#include "FastDelegate/FastDelegate.h"
#include "FastDelegate/FastDelegateBind.h"

/*
	Class for handling user input. Gets input events,
	calls handler function for registred events.

	It was designed to be far more flexible than it is now,
	but never completed. For now, it can handle keyboard input,
	but have troubles with key combinations.
*/
class InputHandler
{
public:
	typedef fastdelegate::FastDelegate<bool (const InputEvent & )> Handler;

private:

	struct KeyboardKey
	{
		int keycode;
		int flags;

		bool operator < ( const KeyboardKey & other ) const
		{
			if ( keycode != other.keycode )
				return keycode < other.keycode;

			  // Ignore flags for now, they work strangely
			//if ( flags != other.flags )
			//	return flags < other.flags;

			return false;
		}
	};
	
	static const int KEYBOARD_HANDLERS_COUNT = KeyboardEvent::KBD_KEY_REPEAT + 1;
	typedef std::map<KeyboardKey, Handler> HandlersMap;
	HandlersMap m_handlers[ KEYBOARD_HANDLERS_COUNT ];

public:
	void ProcessInput( IInput & input );

	void AddKeyboardHandler( const Handler & handler, KeyboardEvent::EType type, int keycode, int flags = 0 );
	template<typename T>
	void AddKeyboardHandler( T *pObject, bool (T::*func)(const InputEvent &), KeyboardEvent::EType type, int keycode, int flags = 0 )
	{
		Handler h;
		h.bind( pObject, func );
		AddKeyboardHandler( h, type, keycode, flags );
	}
	void RemoveKeyboardHandler( KeyboardEvent::EType type, int keycode, int flags = 0 );
	void RemoveKeyboardHandler( KeyboardEvent::EType type, const Handler & handler );
	template<typename T>
	void RemoveKeyboardHandler( KeyboardEvent::EType type, T *pObject, bool (T::*func)(const InputEvent &) )
	{
		Handler h;
		h.bind( pObject, func );
		RemoveKeyboardHandler( type, h );
	}
};
