using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Alvas.Audio;
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using File2 = System.IO.File;//https://stackoverflow.com/questions/3885048/declaring-a-type-synonym-in-c-sharp
// using Microsoft.AspNetCore.Cors;

namespace WebCs.Pages //Controllers
{
    // public class ConvertController : Controller
    // {
    //     public ConvertController()
    //     {
    //     }

    //     public JsonResult Index()
    //     {
    //         return Json("alvas");
    //     }
    // }
    [Route("[controller]")]
    public class ConvertController : Controller
    {
        // GET: api/<controller>
        [HttpGet]
        public IEnumerable<string> Get()
        {
            var path = @"wwwroot\Audio\";
            var files = Directory.GetFiles(path).Select(fn => Path.GetFileName(fn));
            return files; // new string[] { "value1", "value2" };
        }

        private static IAudioReader GetVoxReader(string fileName, int sampleRate)
        {
            BinaryReader br = new BinaryReader(File2.OpenRead(fileName));
            MemoryStream ms = new MemoryStream();
            IntPtr format = AudioCompressionManager.GetPcmFormat(1, 16, sampleRate);
            WaveWriter ww = new WaveWriter(ms, AudioCompressionManager.FormatBytes(format));
            Vox.Vox2Wav(br, ww);
            br.Close();
            return new WaveReader(ms);
        }
        // GET api/<controller>/5
        [HttpGet("{id}")]
        public JsonResult Get(string id)
        {
            try
            {
            var fileName = Path.Combine(@"wwwroot\Audio", id);//"rec2.wav"
            IAudioReader ar;
            // IAudioReader wr = new WaveReader(File2.OpenRead(fileName));
                switch (Path.GetExtension(fileName.ToLower()))
                {
                    case ".vox":
                        ar = GetVoxReader(fileName, 8000);
                        break;
                    case ".avi":
                        ar = new AviReader(File2.OpenRead(fileName));
                        if (!((AviReader)ar).HasAudio)
                        {
                            // MessageBox.Show(string.Format("'{0}' file is not contains audio data", fileName));
                            // return;
            return new JsonResult(new string[] {});
                        }
                        break;
                    case ".au":
                    case ".snd":
                        ar = new AuReader(File2.OpenRead(fileName));
                        break;
                    case ".wav":
                        ar = new WaveReader(File2.OpenRead(fileName));
                        break;
                    case ".mp3":
                        ar = new Mp3Reader(File2.OpenRead(fileName));
                        break;
                    default:
                        ar = new DsReader(fileName);
                        if (!((DsReader)ar).HasAudio)
                        {
                            // ar = null;
                            // MessageBox.Show(string.Format("'{0}' file is not contains audio data", fileName));
            return new JsonResult(new string[] {});
                        }
                        break;
                }
            var format = ar.ReadFormat();
        FormatDetails fd = AudioCompressionManager.GetFormatDetails(format);
        fd.ShowFormatTag = true;
            var data = ar.ReadData();
            Console.WriteLine($"data: {data.Length}");
        FormatDetails[] fdArr = AudioCompressionManager.GetCompatibleFormatList(format);
        for (int i = 0; i < fdArr.Length; i++)
        {
            fdArr[i].ShowFormatTag = true;
            Console.WriteLine(fdArr[i]);
        }
            return new JsonResult(
                new { Format = fd.ToString(), Formats = fdArr.Select(fd => fd.ToString()) }
                );
            // return "value";
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        // POST api/<controller>
        // [EnableCors]
        [HttpPost]
        public JsonResult Post([FromBody]dynamic value) //[FromBody]string file, 
        {
          // https://stackoverflow.com/questions/17832784/how-to-get-post-data-in-webapi
          Console.WriteLine($"selectedIndex: {value}={value.GetType()}");
          string file = value.GetProperty("file").GetString();
          int id = value.GetProperty("id").GetInt32();
          Console.WriteLine($"fileName: {id}");
          string result = Convert(file, id);
          return new JsonResult(result);//$"{file}.wav"
        }

    private string Convert(string file, int ndx)
    {
        //string fileName = Server.MapPath(AudioDir + lbFiles.SelectedValue);
        var fileName = Path.Combine(@"wwwroot\Audio", file);//"rec2.wav"
        try
        {
            IAudioReader wr = null;
            if (Path.GetExtension(fileName).ToLower() != ".wav")
            {
                wr = new DsReader(fileName);
            }
            else
            {
                wr = new WaveReader(File2.OpenRead(fileName));
            }
            //FileStream ms = File2.OpenRead(fileName);
            //WaveReader wr = new WaveReader(ms);

            IntPtr format = wr.ReadFormat();
            //int ndx = lbFormats.SelectedIndex;
            IntPtr formatPcm = AudioCompressionManager.GetCompatibleFormatList(
                format)[ndx].FormatHandle;
            byte[] dataPcm = AudioCompressionManager.Convert(format, formatPcm, wr.ReadData(), false);
            WaveWriter ww = new WaveWriter(File2.Create(fileName + ".wav"),
                AudioCompressionManager.FormatBytes(formatPcm));
            ww.WriteData(dataPcm);
            ww.Close();
            wr.Close();
            return string.Format("The '{0}' file is converted to '{0}.wav' file successfully.", file);
        }
        catch
        {
            return "Converting error.";
        }
        //FillFileList();
    }

        // // PUT api/<controller>/5
        // [HttpPut("{id}")]
        // public void Put(int id, [FromBody]string value)
        // {
        // }

        // // DELETE api/<controller>/5
        // [HttpDelete("{id}")]
        // public void Delete(int id)
        // {
        // }
    }
}