#pragma once

#include "refISoundDevice.h"

namespace FDK
{
	public ref class CSound
	{
	public:
		// 0:最小〜100:原音
		property int n音量
		{
			int get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CSound" );

				float f音量 = 0.0f;
				if( ::BASS_Mixer_ChannelGetEnvelopePos( this->hBassStream, BASS_MIXER_ENV_VOL, &f音量 ) == -1 )
					return 100;

				return (int) ( f音量 * 100 );
			}
			void set( int value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CSound" );

				float f音量 = Math::Min( Math::Max( value, 0 ), 100 ) / 100.0f;	// 0〜100 → 0.0〜1.0
				BASS_MIXER_NODE nodes[ 1 ];
				nodes[ 0 ].pos = 0;
				nodes[ 0 ].value = f音量;
				::BASS_Mixer_ChannelSetEnvelope( this->hBassStream, BASS_MIXER_ENV_VOL, nodes, 1 );
			}
		}

		// 左:-100〜中央:0〜100:右。
		property int n位置
		{
			int get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CSound" );

				float f位置 = 0.0f;
				if( ::BASS_Mixer_ChannelGetEnvelopePos( this->hBassStream, BASS_MIXER_ENV_PAN, &f位置 ) == -1 )
					return 0;

				return (int) ( f位置 * 100 );
			}
			void set( int value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CSound" );

				float f位置 = min( max( value, -100 ), 100 ) / 100.0f;	// -100〜100 → -1.0〜1.0
				BASS_MIXER_NODE nodes[ 1 ];
				nodes[ 0 ].pos = 0;
				nodes[ 0 ].value = f位置;
				::BASS_Mixer_ChannelSetEnvelope( this->hBassStream, BASS_MIXER_ENV_PAN, nodes, 1 );
			}
		}

		// 再生中なら true, 未再生・一時停止中・停止済みなら false を返す。
		property bool b再生中
		{
			bool get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CSound" );

				DWORD dwState = ::BASS_ChannelIsActive( this->hBassStream );
				// デコードチャンネルの場合の戻り値：
				//   BASS_ACTIVE_PLAYING ... デコードすべきデータが残っている
				//   BASS_ACTIVE_STOPPED ... デコードすべきデータがなくなった
				//   BASS_ACTIVE_PAUSED .... デコード一時停止中
				//   BASS_ACTIVE_STALLED ... これが返されることはない

				return ( dwState == BASS_ACTIVE_PLAYING ) ? true : false;
			}
		}

		// 全インスタンスリスト。
		// 「〜を作成する()」メソッドで追加され、「t解放する()」or「Dispose()」で解放される。
		static List<CSound^>^ listインスタンス = gcnew List<CSound^>();

		CSound();
		~CSound();
		!CSound();

		void tWASAPIサウンドを作成する( String^ strファイル名, int hMixer, ESoundDeviceType eデバイス種別 );
		void tWASAPIサウンドを作成する( array<byte>^ byArrWAVファイルイメージ, int hMixer, ESoundDeviceType eデバイス種別 );

		void t先頭から再生する();
		void t一時停止する();
		void t再開する();
		void t停止する();

		void t再生位置を先頭に戻す();
		void t再生位置を変更する( Int64 n位置ms );

		static ESoundDeviceType tサウンドデバイスを自動判別する();

	protected:
		ESoundDeviceType eデバイス種別;
		DWORD hBassStream;
		String^ strファイル名;
		array<byte>^ byArrWAVファイルイメージ;
		GCHandle hGC;

	private:
		CDisposed^ Disposed;
	};
}
