using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace mp3maker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string[] files;
        string tmpBase;
        string tmpExec;
        string msg;
        List<Process> procs;

        private void Form1_Load(object sender, EventArgs e)
        {
            files = null;
            procs = new List<Process>();

            Timer tPrep = new Timer();
            tPrep.Interval = 100;
            tPrep.Start();
            tPrep.Tick += new EventHandler(t_Tick);

            Timer tRun = new Timer();
            tRun.Interval = 100;
            tRun.Start();
            tRun.Tick += new EventHandler(tRun_Tick);

            this.Font = new Font(this.Font.FontFamily, this.Font.SizeInPoints * 1.3f);
        }

        void t_Tick(object sender, EventArgs e)
        {
            ((Timer)sender).Stop();
            msg = label1.Text;
            label1.Text = "Making  temp  directory  ...\n ";
            Application.DoEvents();

            tmpBase = Path.GetTempPath() + "mp3maker";
            if (System.IO.Directory.Exists(tmpBase))
            {
                try
                {
                    System.IO.Directory.Delete(tmpBase, true);
                }
                catch { }
            }
            string salt = (DateTime.UtcNow.Ticks / 10000000) + "";
            tmpExec = tmpBase + "\\" + salt.Substring(salt.Length - 8);
            Directory.CreateDirectory(tmpExec);
            tmpExec += "\\ffmpeg.exe";

            label1.Text = "Extracting  utilities  ...\n ";
            Application.DoEvents();
            System.IO.Stream ffstream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("mp3maker.ffmpeg.exe");
            System.IO.FileStream fso = new FileStream(tmpExec, FileMode.Create, FileAccess.Write);
            ffstream.CopyTo(fso);
            ffstream.Close();
            fso.Close();

            label1.Text = msg;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                Process[] pc = procs.ToArray();
                foreach (Process p in pc)
                {
                    try
                    {
                        p.Kill();
                    }
                    catch { }
                }
                System.Threading.Thread.Sleep(500);
                Directory.Delete(tmpBase, true);
            }
            catch { }
        }

        private void Form1_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            files = ((string[])e.Data.GetData(DataFormats.FileDrop));
        }

        long msec(string str, string re)
        {
            Regex rex2 = new Regex(re);
            MatchCollection mc2 = rex2.Matches(str);
            if (mc2.Count >= 1 && mc2[0].Groups.Count >= 4)
            {
                return
                    Convert.ToInt32(mc2[0].Groups[1].Value) * 100 * 60 * 60 +
                    Convert.ToInt32(mc2[0].Groups[2].Value) * 100 * 60 +
                    Convert.ToInt32(mc2[0].Groups[3].Value) * 100 +
                    Convert.ToInt32(mc2[0].Groups[4].Value);
            }
            return 0;
        }

        void tRun_Tick(object sender, EventArgs e)
        {
            if (files == null) return;
            string[] fl = files;
            files = null;

            Process proc;
            for (int a = 0; a < fl.Length; a++)
            {
                string text = "Analyzing  " + (a + 1) + "  of  " + fl.Length + "  ...\n\n" + fl[a] + "\n\n ";
                label1.Text = text + "\n\n ";
                Application.DoEvents();

                proc = new Process();
                proc.StartInfo = new ProcessStartInfo(tmpExec, "-i \"" + fl[a] + "\" -vn -af volumedetect -f null -");
                proc.StartInfo.StandardErrorEncoding = Encoding.UTF8;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.UseShellExecute = false;
                if (!checkBox1.Checked)
                {
                    proc.StartInfo.CreateNoWindow = true;
                    proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                }
                proc.Start();
                procs.Add(proc);
                //proc.WaitForExit();
                string fulltext = "";
                while (!proc.HasExited)
                {
                    string line = proc.StandardError.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line) && line.Contains("time="))
                    {
                        label1.Text = text + line + "\n\n ";
                        Application.DoEvents();
                    }
                    fulltext += line + "\n";
                }
                proc.WaitForExit();
                procs.Remove(proc);
                //MessageBox.Show(str);
                Regex rex1 = new Regex("\\[.*Parsed_volumedetect_[0-9]* @ [0-9][0-9]*.* max_volume: -([^ ]*) dB");
                MatchCollection mc1 = rex1.Matches(fulltext);
                double boost = 0;
                string boostOpt = "";
                if (mc1.Count >= 1 && mc1[0].Groups.Count >= 2)
                {
                    boost = Convert.ToDouble(mc1[0].Groups[1].Value);
                    if (boost > 0.5)
                    {
                        //boost /= 2.0;
                        boostOpt = "-af volume=" + boost + "dB";
                    }
                }
                long len = msec(fulltext, "\n  Duration: (..):(..):(..)\\.(..),");

                ffmpeg("Ripping", a, fl, len, "-y -i \"" + fl[a] + "\" -vn -map 0:a -acodec copy \"" + fl[a] + ".m4a\"");

                ffmpeg("Converting", a, fl, len, "-y -i \"" + fl[a] + "\" -vn -map 0:a -ab 320k " + boostOpt + " \"" + fl[a] + ".mp3\"");
            }
            System.Media.SystemSounds.Asterisk.Play();
            label1.Text = msg;
        }

        void ffmpeg(string title, int a, string[] fl, long len, string args)
        {
            string text = title + "  " + (a + 1) + "  of  " + fl.Length + "  ...\n\n " + fl[a] + "\n\n ";
            label1.Text = text + "\n\n ";
            Application.DoEvents();

            Process proc = new Process();
            proc.StartInfo = new ProcessStartInfo(tmpExec, args);
            if (!checkBox1.Checked)
            {
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.StandardErrorEncoding = Encoding.UTF8;
            }
            proc.Start();
            procs.Add(proc);
            if (!checkBox1.Checked)
            {
                while (!proc.HasExited)
                {
                    string line = proc.StandardError.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line) && line.Contains("time="))
                    {
                        long pos = msec(line, " time=(..):(..):(..)\\.(..) ");
                        label1.Text = text + line + "\n\n " + Math.Round(100.0 * pos / (1.0 * len), 0) + " %";
                        Application.DoEvents();
                    }
                }
            }
            proc.WaitForExit();
            procs.Remove(proc);
        }
    }
}
