#ifndef __SFJP_MYU__AGH_Keyboard_H__
#define __SFJP_MYU__AGH_Keyboard_H__

#include "agh_class_func_ptr.h"

//class CKeyboardBase;

//namespace kb {
typedef short KEYCODE_t;		//	2バイト目は今のところ使ってない。将来のための予約
typedef short KB_EVTTYPE_t;		//	2バイト目は今のところ使ってない。将来のための予約
//typedef bool (CKeyboardBase::*KB_EVT_HANDLER_CALLBACK)();
typedef bool (_CAghCallbackDummyBaseSI::*KB_EVT_HANDLER_CALLBACK)();
typedef bool (_CAghCallbackDummyBaseSI::*KB_EVT_HANDLER_CALLBACK_SI)();
typedef bool (_CAghCallbackDummyBaseMI::*KB_EVT_HANDLER_CALLBACK_MI)();

#define AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS		(1)	//	押されている間
#define AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN		(2)	//	キーボードが押された瞬間
#define AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP		(3)	//	キーボードが離された瞬間
/*#define MGL_KB_EVT_HANDLER_EVTTYPE_ON_DOWNUP	(8)	//	押した後話した（クリック的な）
#define MGL_KB_EVT_HANDLER_EVTTYPE_ON_PUSH		(MGL_KB_EVT_HANDLER_EVTTYPE_ON_DOWNUP)*/

//	キーボードイベントハンドラ構造体
typedef struct _tagKB_EVT_HANDLER {
	//void* pClassInstance;
	//_CAghCallbackDummyBase* pClassInstance;
	union {
		_CAghCallbackDummyBase* pClassInstance;
		_CAghCallbackDummyBaseSI* pClassInstanceSI;
		_CAghCallbackDummyBaseMI* pClassInstanceMI;
	};
	agh::KB_EVT_HANDLER_CALLBACK pCallbackFunc;
	agh::KB_EVT_HANDLER_CALLBACK_MI pCallbackFuncMI;
	agh::KEYCODE_t keyCode;
	agh::KB_EVTTYPE_t evtType;			//	AGH_KB_EVT_HANDLER_EVTTYPE_ON_〜

	//	コンストラクタ - 2009/08/01
	_tagKB_EVT_HANDLER(){
		pClassInstance = NULL;
		pCallbackFunc = NULL;
		pCallbackFuncMI = NULL;
		keyCode = 0;
		evtType = 0;
	}

} KB_EVT_HANDLER;
//typedef std::list<agh::KB_EVT_HANDLER> KB_EVT_HANDLERS_t;
typedef _AGH_LIST(agh::KB_EVT_HANDLER) KB_EVT_HANDLERS_t;

#include "agh_KeyCode.h"

/////////////////////////////////////////////////////////////////

//	コアの基底クラス
class CKeyboardCoreBase
{
public:
	//	イベントが真ならtrueを、偽ならfalseを返す
	virtual bool IsOnKeyEvt(agh::KB_EVTTYPE_t evtType, agh::KEYCODE_t keyCode)=0;
};

//	キーボード基底クラス
class CKeyboardBase : public agh::CControlBase
{
protected:
	agh::CKeyboardCoreBase *m_pCore;

	//list<bool (*)()> m_kbEventHandlers;	//	本当はvector_list使うネ・・・
	//list<MGL_KB_EVT_HANDLER_CALLBACK> m_kbEventHandlers;	//	本当はvector_list使うネ・・・
	agh::KB_EVT_HANDLERS_t m_kbEventHandlers;	//	本当はvector_list使うネ・・・

	/////////////////////////////////////////////////////////

_AGH_EVENT_ACCESS_MODIFIER:
	///// オーバーライド可能なイベント /////////////////////////////////////////////////
	virtual bool OnFrame();

public:
	//	コンストラクタ
	CKeyboardBase(){}
	virtual ~CKeyboardBase(){}

	//////////////////////////////////////////////////////

	//	キーボードハンドラの登録
	void RegistHandler(agh::KB_EVT_HANDLER &evt){
		m_kbEventHandlers.push_back(evt);
	}

	//	Single Inheritance
	void RegistHandler(
		agh::KB_EVTTYPE_t evtType,
		agh::KEYCODE_t keyCode,		
		agh::KB_EVT_HANDLER_CALLBACK pCallbackFunc,
		void* pClassInstance)
	{
		if ( pClassInstance == NULL )
			pClassInstance = this;

		agh::KB_EVT_HANDLER evt;
		evt.pCallbackFunc = pCallbackFunc;
		evt.keyCode = keyCode;
		evt.evtType = evtType;
		evt.pClassInstance = (_CAghCallbackDummyBase*)pClassInstance;
		m_kbEventHandlers.push_back(evt);
	}

	//	Multiple Inheritance
	void RegistHandler(
		agh::KB_EVTTYPE_t evtType,
		agh::KEYCODE_t keyCode,		
		agh::KB_EVT_HANDLER_CALLBACK_MI pCallbackFunc,
		void* pClassInstance)
	{
		if ( pClassInstance == NULL )
			pClassInstance = this;

		agh::KB_EVT_HANDLER evt;
		evt.pCallbackFuncMI = pCallbackFunc;
		evt.keyCode = keyCode;
		evt.evtType = evtType;
		evt.pClassInstance = (_CAghCallbackDummyBase*)pClassInstance;
		m_kbEventHandlers.push_back(evt);
	}

public:
	enum {
		EVTTYPE_ON_PRESS = AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS,
		EVTTYPE_ON_DOWN = AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN,
		EVTTYPE_ON_UP = AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP
	};
	enum {
		ON_PRESS = AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS,
		ON_DOWN = AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN,
		ON_UP = AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP
	};
	
	/*	VC++ 6.0だと対応してないらしい・・・ウ○コー！
	const static KB_EVTTYPE_t EVTTYPE_ON_PRESS = AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS;
	const static KB_EVTTYPE_t EVTTYPE_ON_DOWN = AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN;
	const static KB_EVTTYPE_t EVTTYPE_ON_UP = AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP;
	const static KB_EVTTYPE_t ON_PRESS = AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS;
	const static KB_EVTTYPE_t ON_DOWN = AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN;
	const static KB_EVTTYPE_t ON_UP = AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP;*/

	//typedef bool (_CAghCallbackDummyBase::*KB_EVT_HANDLER_CALLBACK)();
	typedef KB_EVT_HANDLER_CALLBACK HANDLER_TYPE;
	typedef KB_EVT_HANDLER_CALLBACK CALLBACK_TYPE;
	typedef KB_EVT_HANDLER_CALLBACK_SI CALLBACK_TYPE_SI;
	typedef KB_EVT_HANDLER_CALLBACK_MI CALLBACK_TYPE_MI;

	//typedef _CAghCallbackDummyBase CCallbackBase;
};

////////////////////////////////////////////////////

inline bool CKeyboardBase::OnFrame()
{
	KB_EVT_HANDLERS_t::iterator it=m_kbEventHandlers.begin();
	for(; it!=m_kbEventHandlers.end(); it++)
	{
		agh::KB_EVT_HANDLER &r = *it;

		if ( m_pCore->IsOnKeyEvt(r.evtType, r.keyCode) ){

			//	2009/08/01  多重継承なインスタンス対応

			if ( r.pCallbackFuncMI != NULL )
			{
				//	Multiple Instance
			//	_CAghCallbackDummyBaseMI *miInstance = (_CAghCallbackDummyBaseMI*)r.pClassInstance;
			//	if ( (miInstance->*r.pCallbackFuncMI)() != true )
				if ( (r.pClassInstanceMI->*r.pCallbackFuncMI)() != true )	//	無名union使えばよかった話だった
					return false;
			}
			else
			{
				//	Single Instance
				if ( (r.pClassInstanceSI->*r.pCallbackFunc)() != true )
					return false;
			}


			/*

			//if ( (this->*r.pCallbackFunc)() != true )
			if ( (r.pClassInstance->*r.pCallbackFunc)() != true )
				return false;
			*/

		}

		/*
		switch(r.evtType)
		{
		case AGH_KB_EVT_HANDLER_EVTTYPE_ON_PRESS:
			if ( m_pCore->IsPressKey(r.keyCode) )
				if ( (this->*r.pCallbackFunc)() != true )
					return false;
			break;

		case AGH_KB_EVT_HANDLER_EVTTYPE_ON_DOWN:
			if ( m_pCore->IsOnDownKey(r.keyCode) )
				if ( (this->*r.pCallbackFunc)() != true )
					return false;
			break;

		case AGH_KB_EVT_HANDLER_EVTTYPE_ON_UP:
			if ( m_pCore->IsOnUpKey(r.keyCode) )
				if ( (this->*r.pCallbackFunc)() != true )
					return false;
			break;
		}
		*/
	}

	return true;
}

#endif//__SFJP_MYU__AGH_Keyboard_H__
