using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using NUnit.Framework;
using Utility;

namespace m3uTool.Tests
{
	[TestFixture]
	public class TranscodeTest : ProgressCallbackTestBase
	{
		static string inputMp3 = "Disc 01 - 04.mp3";
		string outputAac = inputMp3.Replace(".mp3", ".aac");
		string outputWav = inputMp3.Replace(".mp3", ".wav");
		private ReaderProgress mReaderProgress = new ReaderProgress();
		private WriterProgress mWriterProgress = new WriterProgress();

		private Stream mPipeStream;

		[Test]
		public void TranscodeSingleThreadTest()
		{
			Mp3FileProperties mp3Info = new Mp3FileProperties(inputMp3);
			Debug.WriteLine(mp3Info);

			mPipeStream = new MemoryStream();

			Mp3ReadThread();
			if (mPipeStream.CanSeek)
				mPipeStream.Seek(0, SeekOrigin.Begin);
			WavWriteThread();
		}

		[Test]
		public void TranscodeMultiThreadTest()
		{
			//mPipeStream = new BridgeStream();
			mPipeStream = new PipeStream();
			(mPipeStream as PipeStream).BlockLastReadBuffer = true;
			(mPipeStream as PipeStream).MaxBufferLength = 1 * PipeStream.MB;

			// mPipeStream.MaxBufferLength = 100;

			Thread writeThread = new Thread(new ThreadStart(AacWriteThread));
			writeThread.Start();

			Thread readThread = new Thread(new ThreadStart(Mp3ReadThread));
			readThread.Start();

			readThread.Join();
			(mPipeStream as PipeStream).BlockLastReadBuffer = false;
			writeThread.Join();
		}

		
		public void Mp3ReadThread()
		{
			//int skip = 3;
			//int limit = 1;
			//string directory = @"C:\tmp\venus bak\media\audiobooks\Bret Easton Ellis - Lunar Park";
			//// string directory = @"C:\tmp\venus bak\media\audiobooks\Clarke, Arthur C. - Space Odyssey 01 - 2001, A Space Odyssey";
			//// string directory = @"C:\tmp\venus bak\media\audiobooks\Guitar Gym\Part 1 - Alternate Picking (Mp3 And Tab)";
			//string[] files = Directory.GetFiles(directory);
			string[] files = new string[]{inputMp3};
			foreach (string mp3File in files)
			{
				//if (skip-- > 0)
				//    continue;
				//if (limit-- == 0)
				//    break;
				Debug.WriteLine(mp3File);
				Mp3FileProperties fp = new Mp3FileProperties(mp3File);
				Debug.WriteLine(fp.ToString());
				// Mp3 to wav
				using (FileStream fileStream = new FileStream(mp3File, FileMode.Open))
				{
					Mp3EncodingOptions opts = new Mp3EncodingOptions();
					opts.Infile = "-";
					opts.Outfile = "-";
					// opts.BitRate = BitRate.KBPS_32;
					// opts.Freeformat = true;
					opts.Mp3Input = true;
					opts.DecodeWav = true;
					// opts.DisableWavHeader = true;
					Debug.WriteLine("MP3 : " + opts.GetCommandLineArguments());
					// opts.Freeformat = true;
					// read from the sr, and write to the memory stream
					using (Mp3Encoder encoder = new Mp3Encoder(opts, mPipeStream))
					{
						encoder.ProgressCallback = mReaderProgress;
						encoder.ProcessInput(fileStream);
					}
				}
			}
		}
		
		public void WavWriteThread()
		{
			using (FileStream fs = new FileStream(outputWav, FileMode.OpenOrCreate))
			using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
			using (StreamReader sr = new StreamReader(mPipeStream, Encoding.Default))
			{
				char[] buffer = new char[1024 * 1024];
				
				while (!sr.EndOfStream)
				{
					int readCount = sr.Read(buffer, 0, buffer.Length);
					sw.Write(buffer, 0, readCount);
					mWriterProgress.SetText("Wrote " + buffer.Length);
				}
				
			}
		}

		public void AacWriteThread()
		{
			Mp4EncodingOptions mp4Opts = new Mp4EncodingOptions();
			mp4Opts.OutputFilename = outputAac;
			mp4Opts.RawPCMSwapInputBytes = true;
			mp4Opts.RawPCMInputMode = true;
			mp4Opts.RawPCMInputSampleRate = 16;
			mp4Opts.RawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
			mp4Opts.RawInputChannels = ChannelMode.Stereo;
			Debug.WriteLine("AAC : " + mp4Opts.GetCommandLineArguments());
			
			using (Mp4Encoder encoder = new Mp4Encoder(mp4Opts))
			{
				encoder.ProgressCallback = mWriterProgress;
				encoder.ProcessInput(mPipeStream);
			}
		}


		private class ReaderProgress : ProgressCallbackTestBase
		{
			public ReaderProgress()
			{
				mPreface = "Reader: ";
			}
			/// <summary>
			/// Call this method from the worker thread to increase the progress 
			/// counter by a specified value.
			/// </summary>
			public override void StepTo(int val)
			{
				if (val % 10 == 0)
				{

					base.StepTo(val);
				}
			}
		}

		private class WriterProgress : ProgressCallbackTestBase
		{
			public WriterProgress()
			{

					mPreface = "\t\t\t\tWriter: ";
			}
						/// <summary>
			/// Call this method from the worker thread to increase the progress 
			/// counter by a specified value.
			/// </summary>
			public override void StepTo(int val)
			{
				if (val % 10 == 0)
				{

					base.StepTo(val);
				}
			}
		}
	}
}
