#ifndef __SFJP_MYU__AGH_Mouse_H__
#define __SFJP_MYU__AGH_Mouse_H__

//class CMouseBase;

//namespace input {
//namespace mouse {
typedef short MOUSECODE_t;		//	2バイト目は今のところ使ってない。将来のための予約
typedef short MOUSE_EVTTYPE_t;	//	2バイト目は今のところ使ってない。将来のための予約
//typedef bool (CKeyboardBase::*MOUSE_EVT_HANDLER_CALLBACK)();
typedef bool (_CAghCallbackDummyBaseSI::*MOUSE_EVT_HANDLER_CALLBACK)(long,long);
typedef bool (_CAghCallbackDummyBaseSI::*MOUSE_EVT_HANDLER_CALLBACK_SI)(long,long);
typedef bool (_CAghCallbackDummyBaseMI::*MOUSE_EVT_HANDLER_CALLBACK_MI)(long,long);

#define AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_PRESS		(1)		//	ボタンが押されている間 / x:y is Position
#define AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_DOWN		(2)		//	ボタンが押された瞬間 / x:y is Position
#define AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_UP			(3)		//	ボタンが離された瞬間 / x:y is Position
#define AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_MOVE		(9)		//	マウスの移動 / x:y is Move Count - 移動量0の場合にはハンドラを呼んではいけない
/*#define MGL_MOUSE_EVT_HANDLER_EVTTYPE_ON_DOWNUP	(8)		//	押した後話した（クリック的な）
#define MGL_MOUSE_EVT_HANDLER_EVTTYPE_ON_PUSH		(MGL_MOUSE_EVT_HANDLER_EVTTYPE_ON_DOWNUP)*/

//	マウスイベントハンドラ構造体
typedef struct _tagMOUSE_EVT_HANDLER {
	//void* pClassInstance;
	//_CAghCallbackDummyBase* pClassInstance;
	union {
		_CAghCallbackDummyBase* pClassInstance;
		_CAghCallbackDummyBaseSI* pClassInstanceSI;
		_CAghCallbackDummyBaseMI* pClassInstanceMI;
	};
	agh::MOUSE_EVT_HANDLER_CALLBACK pCallbackFunc;
	agh::MOUSE_EVT_HANDLER_CALLBACK_MI pCallbackFuncMI;
	agh::MOUSECODE_t mouseCode;
	agh::MOUSE_EVTTYPE_t evtType;		//	AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_〜

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

} MOUSE_EVT_HANDLER;
//typedef std::list<agh::MOUSE_EVT_HANDLER> MOUSE_EVT_HANDLERS_t;
typedef _AGH_LIST(agh::MOUSE_EVT_HANDLER) MOUSE_EVT_HANDLERS_t;

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

#define AGH_MOUSECODE_NULL		(0x00)

#define AGH_MOUSECODE_LBUTTON	(0x11)
#define AGH_MOUSECODE_RBUTTON	(0x12)
#define AGH_MOUSECODE_CBUTTON	(0x13)	//	And Wheel Move (On AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_MOVE)
#define AGH_MOUSECODE_4TH_BTN	(0x14)
#define AGH_MOUSECODE_5TH_BTN	(0x15)
#define AGH_MOUSECODE_6TH_BTN	(0x16)
#define AGH_MOUSECODE_7TH_BTN	(0x17)
#define AGH_MOUSECODE_8TH_BTN	(0x18)

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

//	コアの基底クラス
class CMouseCoreBase
{
public:
	//static const long INVALID_POINT = -9999;
	enum{ INVALID_POINT = -9999 };		//	-1とかだと普通にあるので。
										//	画面サイズが9999とかは流石にないでしょ、ってことでこの値。
										//	（別にもっと大きくしても良いけど見栄え的にで現状はこう）
public:
	//	クリック系の場合は現在位置を、移動系の場合には移動量を返す。
	//	無効な場合は(INVALID_POINT,INVALID_POINT)を返す。
	//	ホイール移動の場合は(z,INVALID_POINT)を返す。
	virtual _AGH_POINT IsOnMouseEvt(agh::MOUSE_EVTTYPE_t evtType, agh::MOUSECODE_t mouseCode)=0;
	
	//	現在のカーソル位置を返す
	virtual _AGH_POINT GetCursorPos()=0;
};

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

//	マウス基底クラス
//template <typename _T_CORE>
class CMouseBase : public agh::CControlBase
{
protected:
	agh::CMouseCoreBase *m_pCore;

	//list<bool (*)()> m_mouseEventHandlers;	//	本当はvector_list使うネ・・・
	//list<MGL_MOUSE_EVT_HANDLER_CALLBACK> m_mouseEventHandlers;	//	本当はvector_list使うネ・・・
	agh::MOUSE_EVT_HANDLERS_t m_mouseEventHandlers;	//	本当はvector_list使うネ・・・

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

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

public:
	//	コンストラクタ
	CMouseBase(){}
	virtual ~CMouseBase(){}
	//CMouseBase(){ m_pCore = new _T_CORE; }
	//virtual ~CMouseBase(){ delete (_T_CORE)m_pCore; /* CMouseCoreBaseを継承していないチョンボに備えてキャストしておく*/ }

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

	//	マウスハンドラの登録
	void RegistHandler(agh::MOUSE_EVT_HANDLER &evt){
		m_mouseEventHandlers.push_back(evt);
	}

	//	Single Inheritance
	void RegistHandler(
		agh::MOUSE_EVTTYPE_t evtType,
		agh::MOUSECODE_t mouseCode,
		agh::MOUSE_EVT_HANDLER_CALLBACK pCallbackFunc,
		void* pClassInstance)
	{
		if ( pClassInstance == NULL )
			pClassInstance = this;

		agh::MOUSE_EVT_HANDLER evt;
		evt.pCallbackFunc = pCallbackFunc;
		evt.mouseCode = mouseCode;
		evt.evtType = evtType;
		evt.pClassInstance = (_CAghCallbackDummyBase*)pClassInstance;
		RegistHandler(evt);
	}

	//	Multiple Inheritance
	void RegistHandler(
		agh::MOUSE_EVTTYPE_t evtType,
		agh::MOUSECODE_t mouseCode,
		agh::MOUSE_EVT_HANDLER_CALLBACK_MI pCallbackFunc,
		void* pClassInstance)
	{
		if ( pClassInstance == NULL )
			pClassInstance = this;

		agh::MOUSE_EVT_HANDLER evt;
		evt.pCallbackFuncMI = pCallbackFunc;
		evt.mouseCode = mouseCode;
		evt.evtType = evtType;
		evt.pClassInstanceMI = (_CAghCallbackDummyBaseMI*)pClassInstance;
		RegistHandler(evt);
	}
	
	virtual _AGH_POINT GetCursorPos()=0;
	virtual _AGH_POINT GetCurPos(){ return GetCursorPos(); }

public:
	enum{
		EVTTYPE_ON_PRESS = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_PRESS,
		EVTTYPE_ON_DOWN = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_DOWN,
		EVTTYPE_ON_UP = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_UP,
		EVTTYPE_ON_MOVE = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_MOVE
	};
	enum{
		ON_PRESS = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_PRESS,
		ON_DOWN = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_DOWN,
		ON_UP = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_UP,
		ON_MOVE = AGH_MOUSE_EVT_HANDLER_EVTTYPE_ON_MOVE
	};
	enum{
		LBUTTON = AGH_MOUSECODE_LBUTTON,
		RBUTTON = AGH_MOUSECODE_RBUTTON,
		CBUTTON = AGH_MOUSECODE_CBUTTON
	};
	
	typedef MOUSE_EVT_HANDLER_CALLBACK_SI HANDLER_TYPE, HANDLER_TYPE_SI, CALLBACK_TYPE, CALLBACK_TYPE_SI;
	typedef MOUSE_EVT_HANDLER_CALLBACK_MI HANDLER_TYPE_MI, CALLBACK_TYPE_MI;
};

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

inline bool CMouseBase::OnFrame()
{
	MOUSE_EVT_HANDLERS_t::iterator it=m_mouseEventHandlers.begin();
	for(; it!=m_mouseEventHandlers.end(); it++)
	{
		agh::MOUSE_EVT_HANDLER &r = *it;

		_AGH_POINT pos = m_pCore->IsOnMouseEvt(r.evtType, r.mouseCode);
		//if ( pos.x != CMouseCoreBase::INVALID_POINT && pos.y != CMouseCoreBase::INVALID_POINT )
		if ( !(pos.x == CMouseCoreBase::INVALID_POINT && pos.y == CMouseCoreBase::INVALID_POINT) )
		{
			//	2009/08/01  多重継承なインスタンス対応

			if ( r.pCallbackFuncMI != NULL )
			{
				//	Multiple Instance
				if ( (r.pClassInstanceMI->*r.pCallbackFuncMI)(pos.x, pos.y) != true )
					return false;
			}
			else
			{
				//	Single Instance
				if ( (r.pClassInstanceSI->*r.pCallbackFunc)(pos.x, pos.y) != true )
					return false;
			}

			/*
			//if ( (this->*r.pCallbackFunc)() != true )
			if ( (r.pClassInstance->*r.pCallbackFunc)(pos.x, pos.y) != true )
				return false;
			*/
		}
	}

	return true;
}

class CHitTestManager : public agh::CControlBase
{
protected:
	agh::CMouseBase *m_pMouse;
	agh::CVisualControlBase *m_pControl;
public:
	//	コンストラクタ・デストラクタ
	CHitTestManager(){ m_pMouse = NULL; }
	virtual ~CHitTestManager(){}
	
	void Setup(agh::CMouseBase *pMouse, agh::CVisualControlBase *pControl){
		m_pMouse = pMouse;
		m_pControl = pControl;
	}
};

#endif//__SFJP_MYU__AGH_Mouse_H__
