using System;
using System.Windows.Forms;

using Microsoft.DirectX.DirectSound;


namespace DarkStrideToolbox
{
	public class DSSoundWrapper
	{
		#region Properties
		private Microsoft.DirectX.DirectSound.Device m_oDirectSoundDevice = null;
		private bool m_bMuted = false;
		private double m_nVolume = 1;
		#endregion


		public DSSoundWrapper( System.Windows.Forms.Control oControl )
		{
			try
			{
				m_oDirectSoundDevice = new Microsoft.DirectX.DirectSound.Device();
				m_oDirectSoundDevice.SetCooperativeLevel( oControl,CooperativeLevel.Priority );

				DSResourceManager.GetGlobalInstance().OnCreateDevice( m_oDirectSoundDevice );
			}
			catch( System.Exception oEx )
			{
				throw new System.Exception( "Unable to instantiate your sound card.",oEx );
			}
		}


		public int PlaySound( string sKey )
		{
			TimeSpan oSpan = TimeSpan.MinValue;
			LoadedSound oLoadedSound = null;
			SecondaryBuffer oSoundBuffer = null;
			bool bFoundBuffer = false;
			int nVolume = 0;
			int nRetIndex = -1;

			
			oLoadedSound = (LoadedSound)DSResourceManager.GetGlobalInstance().GetLoadedSound( sKey );

			//Do we even try to play this sound yet?
			oSpan = DateTime.Now - oLoadedSound.dtLastPlayed;
			if( oLoadedSound.dtLastPlayed == DateTime.MinValue ||
				oSpan.TotalSeconds >= oLoadedSound.nSecondsBetweenPlays )
			{
				for( int i=0 ; i<oLoadedSound.m_oSoundInstances.Count ; i++ )
				{
					if( i >= oLoadedSound.m_oSoundInstances.Count ){ break; } 
					oSoundBuffer = (SecondaryBuffer)oLoadedSound.m_oSoundInstances[ i ];

					//Is this sound available?
					if( oSoundBuffer.Status.Playing == false )
					{
						nRetIndex = i;
						bFoundBuffer = true;
						break;
					}
				}

				//If we didn't find a buffer than we need to make a new one
				if( bFoundBuffer == false )
				{
					if( oLoadedSound.m_oSoundInstances.Count < oLoadedSound.nMaxSoundBuffers || oLoadedSound.nMaxSoundBuffers == -1 )
					{
						oLoadedSound.oStream.Seek( 0,System.IO.SeekOrigin.Begin ); 
						oSoundBuffer = new SecondaryBuffer( oLoadedSound.oStream,m_oDirectSoundDevice );
						oLoadedSound.m_oSoundInstances.Add( oSoundBuffer );

						nRetIndex = oLoadedSound.m_oSoundInstances.Count-1;
					}
					else
					{
						oSoundBuffer = null;
						nRetIndex = -1;
					}
				}

				if( oSoundBuffer != null )
				{
					oLoadedSound.dtLastPlayed = DateTime.Now;
					nVolume = GetBufferVolume();
					oSoundBuffer.Volume = nVolume;
 
					oSoundBuffer.Play( 0,BufferPlayFlags.Default );				
				}
			}
			else
			{
				nRetIndex = -1;
			}

			return( nRetIndex );
		}
		
		public bool SoundIsStillPlaying( string sKey,int nIndex )
		{
			SecondaryBuffer oSoundBuffer = null;
			bool bRetVal = false;


			oSoundBuffer = DSResourceManager.GetGlobalInstance().GetSoundBuffer( sKey,nIndex );
			//Is this sound available?
			bRetVal = ( oSoundBuffer != null && oSoundBuffer.Status.Playing );


			return( bRetVal );
		}
		public void StopPlayingSound( string sKey,int nIndex )
		{
			SecondaryBuffer oSoundBuffer = null;

			oSoundBuffer = DSResourceManager.GetGlobalInstance().GetSoundBuffer( sKey,nIndex );
			//Is this sound available?
			oSoundBuffer.Stop();
		}


		private void ResetVolumes()
		{
			DSSortedList oLoadedSounds = null;
			LoadedSound oLoadedSound = null;
			SecondaryBuffer oSoundBuffer = null;


			//Go through and shut down all the playing sounds
			oLoadedSounds = DSResourceManager.GetGlobalInstance().LoadedSounds;
			for( int i=0 ; i<oLoadedSounds.Count ; i++ )
			{
				oLoadedSound = (LoadedSound)oLoadedSounds.GetByIndex( i );

				for( int nSoundIndex=0 ; nSoundIndex<oLoadedSound.m_oSoundInstances.Count ; nSoundIndex++ )
				{
					oSoundBuffer = (SecondaryBuffer)oLoadedSound.m_oSoundInstances[ nSoundIndex ];
					if( oSoundBuffer.Status.Playing == true )
					{
						oSoundBuffer.Volume = GetBufferVolume();
					}
				}
			}
		}
		private int GetBufferVolume()
		{
			int nRetVal = 0;


			if( m_bMuted == true )
			{
				nRetVal = -10000;
			}
			else
			{
				nRetVal = (int)(  Math.Pow( m_nVolume,4 ) * 10000 - 10000 );

				if( nRetVal < -10000 || nRetVal > 10000 )
				{
					throw new System.Exception( "Volume comes out to be wrong..." + m_nVolume.ToString() + "," + nRetVal.ToString() );
				}
			}


			return( nRetVal );
		}



		#region Properties
		public Microsoft.DirectX.DirectSound.Device DirectSoundDevice
		{
			get
			{
				return( m_oDirectSoundDevice );
			}
		}
		public bool Muted
		{
			get
			{
				return( m_bMuted );
			}
			set
			{
				if( value != m_bMuted )
				{
					m_bMuted = value;
					ResetVolumes();
				}
			}
		}
		public double Volume
		{
			get
			{
				return( m_nVolume );
			}
			set
			{
				if( value != m_nVolume )
				{
					m_nVolume = value;
					ResetVolumes();
				}
			}
		}
		#endregion
	}
}
