using System;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;

namespace m3uTool.Tests
{
    [TestFixture]
    public class Mp3EncoderTests : ProgressCallbackTestBase
    {
        private static void FilesAreEqual(FileInfo file1, FileInfo file2)
        {
            //Assert.AreEqual(file1.Length, file2.Length);

            int filePosition = 0;
            using (FileStream outputOptionFs = file1.OpenRead())
            using (var outputOptionSr = new StreamReader(outputOptionFs))
            using (FileStream streamingFs = file2.OpenRead())
            using (var streamingSr = new StreamReader(streamingFs))
            {
                var outputOptionBuffer = new char[4096];
                var streamingBuffer = new char[4096];

                while (!outputOptionSr.EndOfStream)
                {
                    int outputOptionReadLength = outputOptionSr.Read(outputOptionBuffer, 0, outputOptionBuffer.Length);
                    int streamingReadLength = streamingSr.Read(streamingBuffer, 0, streamingBuffer.Length);

                    Assert.AreEqual(outputOptionReadLength, streamingReadLength);
                    Assert.AreEqual(outputOptionBuffer, streamingBuffer, "offset : " + filePosition);
                    filePosition += outputOptionBuffer.Length;
                }
            }
        }

        /// <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);
        }

        /// <summary>
        /// Tests this instance.
        /// </summary>
        [Test]
        public void StreamingTest()
        {
            String inputWav = "44_16_s.wav";
            string encodedMp3 = "encodedMp3.mp3";
            String decodedWav = "decodedWav.wav";
            String reencodedMp3 = "reencodedMp3.mp3";

            using (var fileStream = new FileStream(encodedMp3, FileMode.OpenOrCreate))
            {
                var encOpts = new Mp3EncodingOptions();
                encOpts.Outfile = "-";
                encOpts.Infile = "-";

                using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
                {
                    enc.ProgressCallback = this;
                    enc.ProcessInput(inputWav);
                }
            }
            Debug.WriteLine("Finished writing " + encodedMp3);

            Debug.WriteLine("Begin writing " + decodedWav);
            using (var fileStream = new FileStream(decodedWav, FileMode.OpenOrCreate))
            {
                var wavOpts = new Mp3EncodingOptions();
                wavOpts.Infile = "-";
                wavOpts.Outfile = "-";
                // wavOpts.MonoDownmixing = true;
                wavOpts.Mp3Input = true;
                wavOpts.DecodeWav = true;

                using (ProcessStreamWrapper enc = new Mp3Encoder(wavOpts, fileStream))
                {
                    enc.ProgressCallback = this;
                    enc.ProcessInput(encodedMp3);
                }
            }
            Debug.WriteLine("Finished writing " + decodedWav);

            using (var fileStream = new FileStream(reencodedMp3, FileMode.OpenOrCreate))
            {
                var encOpts = new Mp3EncodingOptions();
                encOpts.Outfile = "-";
                encOpts.Infile = "-";

                using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
                {
                    enc.ProgressCallback = this;
                    enc.ProcessInput(decodedWav);
                }
            }

            var reencodedProperties = new Mp3FileProperties(reencodedMp3);
            var encodedProperties = new Mp3FileProperties(encodedMp3);
            Assert.AreEqual(encodedProperties.FileLength, reencodedProperties.FileLength);
        }

        /// <summary>
        /// 
        /// </summary>
        [Test]
        public void StreamingVsOutputMp3DecodingTest()
        {
            String input = "44_16_s.mp3";
            String outputOptionDecoded = "outputOptionDecoded.wav";
            String streamingDecoded = "streamingDecode.wav";

            var encOpts = new Mp3EncodingOptions();
            encOpts.Outfile = "-";
            encOpts.Infile = "-";
            encOpts.Mp3Input = true;
            encOpts.DecodeWav = true;

            using (var fileStream = new FileStream(streamingDecoded, FileMode.OpenOrCreate))
            {
                using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
                {
                    enc.ProgressCallback = this;
                    enc.ProcessInput(input);
                }
            }

            encOpts.Outfile = outputOptionDecoded;

            using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
            {
                enc.ProgressCallback = this;
                enc.ProcessInput(input);
            }

            var outputOptionFileInfo = new FileInfo(outputOptionDecoded);
            var streamingFileInfo = new FileInfo(streamingDecoded);

            FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
        }

        /// <summary>
        /// 
        /// </summary>
        [Test]
        public void StreamingVsOutputMp3EncodingTest()
        {
            //String inputWav = "44_16_s.wav";
            String inputWav = "test1.wav";
            String outputOptionEncodedMp3 = "outputOptionEncodedMp3.mp3";
            String streamingEncodedMp3 = "streamingEncodedMp3.mp3";

            var encOpts = new Mp3EncodingOptions();
            encOpts.Outfile = "-";
            encOpts.Infile = "-";

            using (var fs = new FileStream(streamingEncodedMp3, FileMode.OpenOrCreate))
            {
                using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fs))
                {
                    enc.ProgressCallback = this;
                    enc.ProcessInput(inputWav);
                }
            }

            encOpts.Outfile = outputOptionEncodedMp3;

            using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
            {
                enc.ProgressCallback = this;
                enc.ProcessInput(inputWav);
            }

            var outputOptionProperties = new Mp3FileProperties(outputOptionEncodedMp3);
            var streamingProperties = new Mp3FileProperties(streamingEncodedMp3);
            Assert.AreEqual(outputOptionProperties.LengthInSeconds, streamingProperties.LengthInSeconds);

            // FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
        }
    }
}