using System;
using System.Collections.Generic;
using System.Text;

namespace Vortex.Audio {

	/// <summary>
	/// Represents sound source. It is descriptor of sound file which can be played in two modes: streamed or cached into memory.
	/// </summary>
	public class SoundSource : IDisposable {
		///<summary>Internal reference to irrKlang sound source</summary>
		private IrrKlang.ISoundSource _source;

		/// <summary>
		/// Initializes a new instance of the <see cref="SoundSource"/>. Stream mode will be detected automatically.
		/// </summary>
		/// <param name="soundFileName">Name of the sound file.</param>
		public SoundSource(string soundFileName) {
			if (null == soundFileName) throw new ArgumentNullException("soundFileName");

			//just create sound source internal object
			_source = SoundDevice.Instance.Engine.AddSoundSourceFromFile(
				soundFileName
			);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="SoundSource"/> with specified streaming mode. Non-streaming source will be preloaded on create time.
		/// </summary>
		/// <param name="soundFileName">Name of the sound file.</param>
		/// <param name="streamed">Sound source will be streamed if set to <c>true</c>; otherwise it will be loaded into memory until disposed.</param>
		public SoundSource(string soundFileName, bool streamed) {
			if (null == soundFileName) throw new ArgumentNullException("soundFileName");

			_source = SoundDevice.Instance.Engine.AddSoundSourceFromFile(
				soundFileName,
				streamed ? IrrKlang.StreamMode.Streaming : IrrKlang.StreamMode.NoStreaming,
				!streamed
			);
		}

		#region IDisposable Members

		/// <summary>
		/// Destroys unmanaged resource linked with this sound source
		/// </summary>
		public void Dispose() {
			_source.Dispose();
		}

		#endregion

		/// <summary>
		/// Gets or sets the start sound volume.
		/// </summary>
		/// <value>The start sound volume.</value>
		public float StartVolume {
			get { return _source.DefaultVolume; }
			set { _source.DefaultVolume = value; }
		}

		/// <summary>
		/// Gets a value indicating whether this sound source supports seeking.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this source supports seeking; otherwise, <c>false</c>.
		/// </value>
		public bool IsSeekingSupported {
			get { return _source.IsSeekingSupported; }
		}

		/// <summary>
		/// Gets the length of sound source in milliseconds.
		/// </summary>
		/// <value>The length of sound in milliseconds.</value>
		public uint Length {
			get { return _source.PlayLength; }
		}

		/// <summary>
		/// Plays specified source only once without generating sound tracking object.
		/// </summary>
		public void PlayOnce() {
			Play().Dispose();
		}

		/// <summary>
		/// Plays specified source generating sound tracking object.
		/// </summary>
		public Sound Play() {
			return Play(false, false);
		}

		/// <summary>
		/// Plays the specified sound creating specified sound tracking object.
		/// </summary>
		/// <param name="startLooped">if set to <c>true</c> then sound will be looped.</param>
		/// <returns></returns>
		public Sound Play(bool startLooped) {
			return Play(startLooped, false);
		}

		/// <summary>
		/// Plays the specified sound creating specified sound tracking object.
		/// </summary>
		/// <param name="startLooped">if set to <c>true</c> then sound will be looped.</param>
		/// <param name="startPaused">if set to <c>true</c> then sound will be started paused and need to be resumed calling ISound.Resume().</param>
		/// <returns></returns>
		public Sound Play(bool startLooped, bool startPaused) {
			return new Sound(
				SoundDevice.Instance.Engine.Play2D(_source, startLooped, startPaused, false)
			);
		}

	}
}
