#pragma once

#include "refIInputDevice.h"
#include "enumKey.h"

namespace FDK
{
	public ref class CInputMIDI : IInputDevice
	{
	public:
		property UInt32 hMidiIn
		{
			UInt32 get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_hMidiIn;
			}
			void set( UInt32 value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_hMidiIn = value;
			}
		}
		property List<CInputEvent^>^ listMIDI入力イベント
		{
			List<CInputEvent^>^ get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_listMIDI入力イベント;
			}
		protected:
			void set( List<CInputEvent^>^ value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_listMIDI入力イベント = value;
			}
		}

		CInputMIDI( UInt32 nID );
		~CInputMIDI();
		
		// このメソッドは midiInProc スレッドから呼び出される。（要同期）
		void tメッセージからMIDI信号のみ受信( UInt16 wMsg, UInt32 dwInstance, UInt32 dwParam1, UInt32 dwParam2, Int64 n受信システム時刻 );

		#pragma region [ IInputDevice 実装 ]
		//-----------------
		property E入力デバイス種別 e入力デバイス種別
		{
			virtual E入力デバイス種別 get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_e入力デバイス種別;
			}
		protected:
			void set( E入力デバイス種別 value ) 
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_e入力デバイス種別 = value;
			}
		}
		property Guid^ guid
		{
			virtual Guid^ get()
			{ 
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_guid;
			}
		protected:
			void set( Guid^ value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_guid = value;
			}
		}
		property int ID 
		{
			virtual int get()
			{ 
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_ID;
			}
		protected:
			void set( int value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_ID = value;
			}
		}
		property List<CInputEvent^>^ list入力イベント
		{
			virtual List<CInputEvent^>^ get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

				lock l( this->lock入力イベント );
				return this->_list入力イベント;
			}
		protected:
			void set( List<CInputEvent^>^ value ) 
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

				lock l( this->lock入力イベント );
				this->_list入力イベント = value; 
			}
		}
		property String^ strデバイス名
		{
			virtual String^ get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				return this->_strデバイス名;
			}
			virtual void set( String^ value ) 
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );
				this->_strデバイス名 = value;
			}
		}

		virtual void tポーリング( bool bWindowがアクティブ中, bool bバッファ入力を使用する );

		virtual bool bキーが押された( int nKey )
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

			lock l( this->lock入力イベント );

			for each( CInputEvent^ ie in this->_list入力イベント )
			{
				if( ( ie->nKey == nKey ) && ie->b押された )
					return true;
			}
			return false;
		}
		virtual bool bキーが押された( Key key )
		{
			return this->bキーが押された( (int) key );
		}
		
		virtual bool bキーが押されている( int nKey )
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

			return false;	// 未対応
		}
		virtual bool bキーが押されている( Key key )
		{
			return this->bキーが押されている( (int) key );
		}
		
		virtual bool bキーが離された( int nKey )
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

			return false;	// 未対応
		}
		virtual bool bキーが離された( Key key )
		{
			return this->bキーが離された( (int) key );
		}

		virtual bool bキーが離されている( int nKey )
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CInputMIDI" );

			return false;	// 未対応
		}
		virtual bool bキーが離されている( Key key )
		{
			return this->bキーが離されている( (int) key );
		}
		//-----------------
		#pragma endregion

	private:
		CDisposed^ Disposed;
		UInt32 _hMidiIn;
		List<CInputEvent^>^ _listMIDI入力イベント;
		E入力デバイス種別 _e入力デバイス種別;
		Guid^ _guid;
		int _ID;
		List<CInputEvent^>^ _list入力イベント;
		String^ _strデバイス名;

		Object^ lock入力イベント;			// list入力イベント＆要素のロック用。
		Object^ lockMIDI入力イベント;		// listMIDI入力イベント＆要素のロック用。（MIDIの入力ロックは専用とし、他のロックで止められないようにする）
	};
}