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

namespace m3uTool
{
	/// <summary>
	///FAAC 1.24.1 (May 17 2005) UNSTABLE
	///
	///Usage: faac [options] infiles ...
	///Options:
	///  -q <quality>  Set quantizer quality.
	///  -b <bitrate>  Set average bitrate to x kbps. (ABR, lower quality mode)
	///  -c <freq>     Set the bandwidth in Hz. (default=automatic)
	///  -o X          Set output file to X (only for one input file)
	///  -r            Use RAW AAC output file.
	///  -P            Raw PCM input mode (default 44100Hz 16bit stereo).
	///  -R            Raw PCM input rate.
	///  -B            Raw PCM input sample size (8, 16 (default), 24 or 32bits).
	///  -C            Raw PCM input channels.
	///  -X            Raw PCM swap input bytes
	///  -I <C,LF>     Input channel config, default is 3,4 (Center third, LF fourth)
	///
	///MP4 specific options:
	///  -w            Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
	///  --artist X    Set artist to X
	///  --writer X    Set writer to X
	///  --title X     Set title to X
	///  --genre X     Set genre to X
	///  --album X     Set album to X
	///  --compilation Set compilation
	///  --track X     Set track to X (number/total)
	///  --disc X      Set disc to X (number/total)
	///  --year X      Set year to X
	///  --cover-art X Read cover art from file X
	///  --comment X   Set comment to X
	/// </summary>
	public class Mp4EncodingOptions : ProcessArguments
	{
		#region Private variables

		/// <summary>
		/// Files to use for input
		/// </summary>
		private string[] mInfiles;
		
		/// <summary>
		/// Quantinizer Quality -q [quality]
		/// </summary>
		private int mQuantinizerQuality = int.MinValue;
		/// <summary>
		/// BitRate -b [bitrate]
		/// </summary>
		private int mBitrate = int.MinValue;
		/// <summary>
		/// The bandwidth in Hz -c [freq]
		/// </summary>
		private SampleRateFrequency mBandwidth = SampleRateFrequency.Hz_0;

		/// <summary>
		/// The output filename (only for one input file) -o [filename]
		/// </summary>
		private string mOutputFilename = null;

		/// <summary>
		/// Use RAW AAC output file -r
		/// </summary>
		private bool mRawAACOutputFile = false;

		/// <summary>
		/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
		/// </summary>
		private bool mRawPCMInputMode = false;

		/// <summary>
		/// Raw PCMInputSampleSize (default 44100Hz 16bit stereo) -R
		/// </summary>
		private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;

		/// <summary>
		/// Raw PCM input rate (default 16) -B
		/// </summary>
		private int mRawPCMInputSampleRate = 16;

		/// <summary>
		/// Raw PCM input channels -C
		/// </summary>
		private ChannelMode mRawInputChannels;

		/// <summary>
		/// Raw PCM swap input bytes -X
		/// </summary>
		private bool mRawPCMSwapInputBytes = false;

		/// <summary>
		/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a) -w
		/// </summary>
		private bool mWrapAACDataInMp4 = false;

		/// <summary>
		/// Set artist to X  --artist X 
		/// </summary>
		private string mArtist = null;

		/// <summary>
		/// Set writer to X  --writer X
		/// </summary>
		private string mWriter = null;

		/// <summary>
		/// Set title to X  --title X
		/// </summary>
		private string mTitle = null;

		/// <summary>
		/// Set genre to X  --genre X
		/// </summary>
		private string mGenre = null;

		/// <summary>
		/// Set album to X  --album X
		/// </summary>
		private string mAlbum = null;

		/// <summary>
		/// Set compilation  --compilation
		/// </summary> 
		private string mCompilation = null;

		/// <summary>
		/// Set track to X (number/total)  --track X
		/// </summary>
		private string mTrack = null;

		/// <summary>
		/// Set disc to X (number/total)  --disc X
		/// </summary>
		private string mDisc = null;

		/// <summary>
		/// Set year to X  --year X
		/// </summary>
		private int mYear = int.MinValue;

		/// <summary>
		/// Load cover art from filename  --cover-art X
		/// </summary>
		private string mCoverArtFilename = null;

		/// <summary>
		/// Set comment to X  --comment X
		/// </summary>
		private string mComment = null;

		#endregion

		/// <summary>
		/// Gets or sets the input files.
		/// </summary>
		/// <value>The input files.</value>
		public string[] InputFiles
		{
			get
			{
				if (mInfiles == null)
					return new string[]{};
				return mInfiles;
			}
			set
			{
				mInfiles = value;
			}
		}

		/// <summary>
		/// Quantinizer Quality -q [quality]
		/// </summary>
		public int QuantinizerQuality
		{
			get { return mQuantinizerQuality; }
			set { mQuantinizerQuality = value; }
		}

		/// <summary>
		/// BitRate -b [bitrate]
		/// </summary>
		public int Bitrate
		{
			get { return mBitrate; }
			set { mBitrate = value; }
		}

		/// <summary>
		/// The bandwidth in Hz -c [freq]
		/// </summary>
		public SampleRateFrequency Bandwidth
		{
			get { return mBandwidth; }
			set { mBandwidth = value; }
		}

		/// <summary>
		/// The output filename (only for one input file) -o [filename]
		/// </summary>
		public string OutputFilename
		{
			get { return mOutputFilename; }
			set { mOutputFilename = value; }
		}

		/// <summary>
		/// Use RAW AAC output file -r
		/// </summary>
		public bool RawAACOutputFile
		{
			get { return mRawAACOutputFile; }
			set { mRawAACOutputFile = value; }
		}

		/// <summary>
		/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
		/// </summary>
		public bool RawPCMInputMode
		{
			get { return mRawPCMInputMode; }
			set { mRawPCMInputMode = value; }
		}

		/// <summary>
		/// Raw PCMInputSampleSize -R
		/// </summary>
		public SampleRateFrequency RawPCMInputSampleSize
		{
			get { return mRawPCMInputSampleSize; }
			set
			{
				 mRawPCMInputSampleSize = value;
				 RawPCMInputMode = true;
			}
		}

		/// <summary>
		/// Raw PCM input rate (default 16) -B
		/// </summary>
		public int RawPCMInputSampleRate
		{
			get { return mRawPCMInputSampleRate; }
			set
			{
				mRawPCMInputSampleRate = value;
				RawPCMInputMode = true;
			}
		}

		/// <summary>
		/// Raw PCM input channels -C
		/// </summary>
		public ChannelMode RawInputChannels
		{
			get { return mRawInputChannels; }
			set
			{
				mRawInputChannels = value;
				RawPCMInputMode = true;
			}
		}

		/// <summary>
		/// Raw PCM swap input bytes -X
		/// </summary>
		public bool RawPCMSwapInputBytes
		{
			get { return mRawPCMSwapInputBytes; }
			set
			{
				mRawPCMSwapInputBytes = value;
				RawPCMInputMode = true;
			}
		}

		/// <summary>
		/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
		/// </summary>
		public bool WrapAACDataInMp4
		{
			get { return mWrapAACDataInMp4; }
			set { mWrapAACDataInMp4 = value; }
		}

		/// <summary>
		/// Set artist to X
		/// </summary>
		public string Artist
		{
			get { return mArtist; }
			set
			{
				mArtist = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set writer to X
		/// </summary>
		public string Writer
		{
			get { return mWriter; }
			set
			{
				mWriter = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;

			}
		}

		/// <summary>
		/// Set title to X
		/// </summary>
		public string Title
		{
			get { return mTitle; }
			set
			{
				mTitle = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set genre to X
		/// </summary>
		public string Genre
		{
			get { return mGenre; }
			set
			{
				mGenre = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set album to X
		/// </summary>
		public string Album
		{
			get { return mAlbum; }
			set
			{
				mAlbum = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set compilation
		/// </summary>
		public string Compilation
		{
			get { return mCompilation; }
			set
			{
				mCompilation = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set track to X (number/total)
		/// </summary>
		public string Track
		{
			get { return mTrack; }
			set
			{
				 mTrack = value;
				 if (!string.IsNullOrEmpty(value))
					 WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set disc to X (number/total)
		/// </summary>
		public string Disc
		{
			get { return mDisc; }
			set
			{
				mDisc = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Set year to X
		/// </summary>
		public int Year
		{
			get { return mYear; }
			set
			{
				mYear = value;
				if (value != int.MinValue)
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Load cover art from filename
		/// </summary>
		public string CoverArtFilename
		{
			get { return mCoverArtFilename; }
			set
			{
				mCoverArtFilename = value;
				if (!string.IsNullOrEmpty(value))
					WrapAACDataInMp4 = true;
			}
		}

		/// <summary>
		/// Quantinizer Quality -q [quality]
		/// </summary>
		public string Comment
		{
			get { return mComment; }
			set
			{
				 mComment = value;
				 if (!string.IsNullOrEmpty(value))
					 WrapAACDataInMp4 = true;
			}
		}
		
		/// <summary>
		/// Gets a string representing the command line arguments specified by the properties in the object.
		/// </summary>
		/// <returns></returns>
		public override string GetCommandLineArguments()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (mQuantinizerQuality != int.MinValue)
				stringBuilder.Append(" -q " + mQuantinizerQuality);
			if (mBitrate != int.MinValue)
				stringBuilder.Append(" -b " + mBitrate);
			if (mBandwidth != SampleRateFrequency.Hz_0)
				stringBuilder.Append(" -c " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mBandwidth));

			if (!string.IsNullOrEmpty(mOutputFilename))
			{
				if (mOutputFilename.Trim() == "-")
					stringBuilder.Append(" -o-");
				else
					stringBuilder.Append(" -o " + GetQuotedCommandLineArgument(mOutputFilename));
			}
			else
				stringBuilder.Append(" -o-");
			
			if (mRawPCMInputMode)
			{
				stringBuilder.Append(" -P ");
				if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
					stringBuilder.Append(" -R " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
				if (mRawPCMInputSampleRate != 16)
					stringBuilder.Append(" -B " + mRawPCMInputSampleRate);
				int chanelMode = ChannelModeUtility.GetChannelModeInt(mRawInputChannels);
				if (chanelMode != 2)
					stringBuilder.Append(" -C " + chanelMode);
				if (mRawPCMSwapInputBytes)
					stringBuilder.Append(" -X ");
			}

			if (mWrapAACDataInMp4)
			{
				stringBuilder.Append(" -w ");
				if (!string.IsNullOrEmpty(mArtist))
					stringBuilder.Append(" --artist " + mArtist);
				if (!string.IsNullOrEmpty(mWriter))
					stringBuilder.Append(" --writer " + mWriter);
				if (!string.IsNullOrEmpty(mTitle))
					stringBuilder.Append(" --title " + mTitle);
				if (!string.IsNullOrEmpty(mGenre))
					stringBuilder.Append(" --genre " + mGenre);
				if (!string.IsNullOrEmpty(mAlbum))
					stringBuilder.Append(" --album " + mAlbum);
				if (!string.IsNullOrEmpty(mCompilation))
					stringBuilder.Append(" --compilation " + mCompilation);
				if (!string.IsNullOrEmpty(mTrack))
					stringBuilder.Append(" --track " + mTrack);
				if (!string.IsNullOrEmpty(mDisc))
					stringBuilder.Append(" --disc " + mDisc);
				if (mYear != int.MinValue)
					stringBuilder.Append(" --year " + mYear);
				if (!string.IsNullOrEmpty(mCoverArtFilename))
					stringBuilder.Append(" --cover-art " + mCoverArtFilename);
				if (!string.IsNullOrEmpty(mComment))
					stringBuilder.Append(" --comment " + mComment);
			}
			if (mInfiles != null && mInfiles.Length > 0)
			{
				// use standard input
				if (mInfiles[0].Trim() == "-")
					stringBuilder.Append(" -");
				else
				{
					foreach (string infile in mInfiles)
						stringBuilder.Append(" " + GetQuotedCommandLineArgument(infile));
				}
			}
			else
				stringBuilder.Append(" -");
				

			return stringBuilder.ToString();
		}
	}
}
