/**
 * @file Input.h
 * @brief 入力（キーボード・マウス・ジョイスティック）のインターフェース、定数定義などを行う.
 * 実際の処理は、OS依存の実装クラスに任せます。
 *
 * @author S.F.
 * @version $Id:
 *
 * Copyright (C) 2000-2002 Satoshi Fujiwara. All Rights Reserved.
 */

/// 二重読み込み防止マクロ
#if !defined(AFX_INPUT_H__D4B94DF3_02D8_42CE_AC7A_A98CCC9D0115__INCLUDED_)
#define AFX_INPUT_H__D4B94DF3_02D8_42CE_AC7A_A98CCC9D0115__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "sf.h"
extern "C" {
namespace sf{
	namespace system {
		/// 入力周りのクラス・定数などはすべてここに含まれます。
		namespace input {
			/// マウス関連のクラス・定数などはすべてここに含まれます
			namespace mouse {
				/// マウスイベントで同時に押されたキーコードを列挙する
				enum MKEY_CODE {
					MKEY_CONTROL = 0x1,///< コントロールキーマスク
					MKEY_LBUTTON = 0x2,///< マウス左ボタンマスク
					MKEY_RBUTTON = 0x4,///< マウス右ボタンマスク
					MKEY_SHIFT = 0x8,///< シフトキーマスク
					WHEEL_MASK = 0xffff0000///< マウスホイールマスク
				};

				/** マウスイベントリスナ−
				 *
				 * マウスイベントのリスナーです。マウスのイベントはすべてこのリスナーインターフェースを通じて行われます。<br>
				 * マウスイベントを処理したい場合、このインターフェースを継承して実装し、イベントを発行するInputインターフェースの
				 * Input::addMouseListener()メソッドで登録します。
				 */
				class Listener 
				{
				public:

					/** 左ボタンが押された.
					 * マウスの左ボタンが押されたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void leftButtonDown(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** 左ボタンが離された.
					 * マウスの左ボタンが離されたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void leftButtonUp(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** 左ボタンがダブルクリックされた.
					 * マウスの左ボタンがダブルクリックされたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void leftButtonDoubleClick(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** 右ボタンが押された.
					 * マウスの右ボタンが押されたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE*/
					virtual void rightButtonDown(const int screenX,const int screenY,const DWORD mkey) = 0;
				
					/** 右ボタンが離された.
					 * マウスの右ボタンが離されたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void rightButtonUp(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** 右ボタンがダブルクリックされた.
					 * マウスの右ボタンがダブルクリックされたときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void rightButtonDoubleClick(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** マウスカーソル座標が変化した.
					 * マウスカーソル座標が変化したときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void mouseMove(const int screenX,const int screenY,const DWORD mkey) = 0;

					/** マウスホイールの位置が変化した.
					 * マウスホイールの位置が変化したときに呼び出されるメソッドです。
					 * @param screenX スクリーン上のマウスX座標
					 * @param screenY スクリーン上のマウスY座標
					 * @param mkey 同時に押されたキーコード @ref MKEY_CODE */
					virtual void mouseWheel(const int screenX,const int screenY,const DWORD mkey) = 0;
					
					/** マウスイベントを受け取る状態かどうかを問い合わせる.
					 * @retval true 現在マウスイベントを受け取っている
					 * @retval false 現在マウスイベントを拒否している */
					virtual const bool isListeningMouse(void) const = 0;

					/** マウスイベントを発行するTalkerが削除された. 
					 * マウスイベントを発行するTalkerが削除される時に呼ばれます。
					 * このメソッドが呼ばれた以降は、リスナー側はInput::removeMouseListener()を呼び出してはいけません。*/					 
					virtual void mouseTalkerIsDeleted(void) = 0;
				};
			};

			/// キーボード関連の定数・クラスはすべてここに含まれます。
			namespace keyboard {
				/// 特殊キーコード
				enum EXTEND_KEYCODE {
					CONTROL = 0x1,///< コントロールキー
					SHIFT   = 0x8///< シフトキー
				};

				/// 仮想キーコード
				enum VIRTUAL_KEYCODE {
					VKEY_LEFT = 0x25,///< 左カーソルキー 
					VKEY_UP = 0x26,///< 上カーソルキー
					VKEY_RIGHT = 0x27,///< 右カーソルキー
					VKEY_DOWN = 0x28///< 下カーソルキー
				};

				/** 仮想キーコードクラス. 
				 * @note なぜこんなクラスがあるのか現在不明
				 */
				class SFDLL VKey {
				public:
					static const int UP;///< 上カーソルキー
					static const int DOWN;///< 下カーソルキー
					static const int LEFT;///< 左カーソルキー
					static const int RIGHT;///< 右カーソルキー
				};

				/** キーボードイベントリスナ−.
				 *
				 * キーボードイベントのリスナーです。キーボードのイベントはすべてこのリスナーインターフェースを通じて行われます。<br>
				 * キーボードイベントを処理したい場合、このインターフェースを継承して実装し、イベントを発行するInputインターフェースの
				 * Input::addKeyboardListener()メソッドで登録します。*/
	            class Listener 
				{
				public:
					/** キーが押された. 
				     * キーが押された場合に呼び出されます。
					 * @param keyCode キーコード
					 * @param extKeyCode 拡張キーコード EXTEND_KEYCODE を参照 */
					virtual void keyDown(const DWORD keyCode,const DWORD extKeyCode) = 0;

					/** キーが離された. 
				     * キーが離された場合に呼び出されます。
					 * @param keyCode キーコード
					 * @param extKeyCode 拡張キーコード @ref EXTEND_KEYCODE を参照 */
					virtual void keyUp(const DWORD keyCode,const DWORD extKeyCode) = 0;

					/** キーボードイベントを受け取る状態かどうかを問い合わせる.
					 * TalkerがListenerが現在キーボードイベントを受け取る状態にあるかどうか確認するためのメソッドです。<br>
					 * 一時的にキーボードイベントを受け取りたくない場合はこのメソッドが呼ばれたときにfalseを返します。
					 * @retval true 現在キーボードイベントを受け取っている
					 * @retval false 現在キーボードイベントを拒否している */
					virtual const bool isListeningKeyboard(void) const = 0;
					
					/** キーボードイベントを発行するTalkerが削除された. 
					 * キーボードイベントを発行するTalkerが削除される時に呼ばれます。<br>
					 * これが呼ばれたら、Talker自身はメモリ上に存在しないことになるので、
					 * このメソッドが呼ばれた以降は、リスナー側は絶対にInput::removeKeyboardListener()を呼び出してはいけません。
					 * 誤って呼び出した後の状態は不定となります。 */					 
					virtual void keyboardTalkerIsDeleted(void) = 0;
				};
			};
			
			/// 入力機器コントロール.
			/*! インプットデバイスのコントロールを行うインターフェースです */
			class Input  
			{
				// LIFECYCLE //
			public:
				/// コンストラクタ
				Input(){};
				/// デストラクタ
				virtual ~Input(){};
				// OPERATORS //
				// OPERATIONS //
				/// Inputインターフェースの初期化
				/*! Inputインターフェースの実装クラスを初期化するために用意されています。<br>
				    通常ライブラリを利用する側からこのメソッドを呼び出すことはありません。 
					@throw FatalErrorException 初期化に失敗した場合もしくは入力デバイスが何も見つからなかった場合 */
				virtual void initialize(void) = 0;

				/** 入力デバイスの状態の更新. 
				 * 入力デバイスの状態を読み取り、関連する変数を更新します。*/
				virtual void update(void) = 0;

				/** マウスリスナーの登録.
				 * mouse::Listener を登録します。<br>
				 * マウスイベントを受け取りたいクラスはmouse::Listenerインターフェースを実装し、
				 * このメソッドで登録することによりマウスイベントを受け取ることができます。 
				 * @param pListener mouse::Listener インターフェースのポインタ */
				virtual void addMouseListener(mouse::Listener * const pListener) = 0;
				
				/** マウスリスナーの削除.
				 * mouse::Listener を削除します。<br>
				 * mouse::Listener 自身が削除されるとき、このメソッドを呼び出して、Talkerに自身の削除を通知します。
				 * @param pListener mouse::Listener インターフェースのポインタ */
				virtual	void removeMouseListener(mouse::Listener * const pListener) = 0;

				/** キーボードリスナーの登録.
				 * keyboard::Listener を登録します。<br>
				 * キーボードイベントを受け取りたいクラスはkeyboard::Listenerインターフェースを実装し、
				 * このメソッドで登録することによりキーボードイベントを受け取ることができます。 
				 * @param pListener keyboard::Listener インターフェースのポインタ */
				virtual void addKeyboardListener(keyboard::Listener * const pListener) = 0;

				/** キーボードリスナーの削除.
				 * keyboard::Listener を削除します。<br>
				 * keyboard::Listener 自身が削除されるとき、このメソッドを呼び出して、Talkerに自身の削除を通知します。
				 * @param pListener keyboard::Listener インターフェースのポインタ */
				virtual void removeKeyboardListener(keyboard::Listener * const pListener) = 0;

				// ACCESS //

				/** 左ボタンが押されたかどうか. 
				 * 左ボタン(ジョイスティック・カーソルキー）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool left(const bool bTrig = false) const = 0;

				/** 右ボタンが押されたかどうか. 
				 * 右ボタン(ジョイスティック・カーソルキー）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool right(const bool bTrig = false) const = 0;

				/** 上ボタンが押されたかどうか. 
				 * 上ボタン(ジョイスティック・カーソルキー）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool up(const bool bTrig = false) const = 0;

				/** 下ボタンが押されたかどうか. 
				 * 下ボタン(ジョイスティック・カーソルキー）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool down(const bool bTrig = false) const = 0;

				/** Aボタンが押されたかどうか. 
				 * Aボタン(ジョイスティックのAボタン・キーボードのZ）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool buttonA(const bool bTrig = false) const = 0;

				/** Bボタンが押されたかどうか. 
				 * Bボタン(ジョイスティックのBボタン・キーボードのX）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool buttonB(const bool bTrig = false) const = 0;

				/** Cボタンが押されたかどうか. 
				 * Cボタン(ジョイスティックのCボタン・キーボードのC）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool buttonC(const bool bTrig = false) const = 0;

				/** Dボタンが押されたかどうか. 
				 * Dボタン(ジョイスティックのDボタン・キーボードのV）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool buttonD(const bool bTrig = false) const = 0;

				/** startボタンが押されたかどうか. 
				 * startボタン(ジョイスティックのAボタン・キーボードのspace）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool start(const bool bTrig = false) const = 0;

				/** exitボタンが押されたかどうか. 
				 * exitボタン(キーボードのESC）が押された場合にtrueを返します。<br>
				 * @param bTrig false の時は、押しっぱなしの場合でもtrueを返却します。<br>
				 * trueの場合は、実際にボタンが押されたときのみ、trueを返却します。
				 * @retval true ボタンが押されている
				 * @retval false ボタンが押されていない　*/
				virtual const bool exit(const bool bTrig = false) const = 0;

				/** マウスカーソルを表示する */
				virtual void showMouseCursor(void) = 0;
				/** マウスカーソルを隠す */
				virtual void hideMouseCursor(void) = 0; 
				/** 現在のマウスカーソルの状態を問い合わせる 
				 @retval true マウスカーソルは表示されています。
				 @retval false マウスカーソルは非表示となっています。*/
				virtual const bool mouseCursorVisibility(void) const = 0;

				// INQUIRY //
				/** 現在のInputインターフェースの状態を問い合わせる 
				 * @retval true 現在、利用可能です。
				 * @retval false 現在、利用不可能です。*/
				virtual const bool isEnabled(void) const = 0;
			};
			// ----------------------------------------------------------------
			/// イベントリスナークラス 
			// ----------------------------------------------------------------
			class Listener
			{
			public:
				virtual void deviceStateChanged(Input * const pInput) = 0;
				virtual void eventTalkerIsDeleted(void) = 0;
			};// Listener
			

		}// namespace input
	}// namespace system
}// namespace sf
}
#endif // !defined(AFX_INPUT_H__D4B94DF3_02D8_42CE_AC7A_A98CCC9D0115__INCLUDED_)
