using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;

namespace MKVTest
{
    /* Call mkvpropedit.exe
     * Edit "Title" detail property: --edit info --set "title=%TITLE%" %FILE%
     * Edit video track one: --edit track:v1 --set "name(or language)="%VAR%" %FILE%
     * Edit audio track one: --edit track:a1 --set "name(or language)="%VAR%" %FILE%
     * To add simply replace "--set" with "--add".
     */
    public partial class Form1 : Form
    {
        public static string Language = "eng";
        private static readonly ContextMenuStrip menu = new ContextMenuStrip();

        public Form1()
        {
            InitializeComponent();
            inputFilesListView.ItemSelectionChanged += UpdateFilePropPrediction;
            inputFilesListView.MouseClick += ShowMenu;
            Resize += Form1_Resize;

            var item = new ToolStripMenuItem
            {
                Name = "RemoveItem",
                Text = @"Remove"
            };
            menu.Items.Add(item);

            var inputColumn = new ColumnHeader
            {
                Text = @"Files",
                Name = @"HeaderColumn",
                Width = inputFilesListView.Width - 10
            };
            inputFilesListView.Columns.Add(inputColumn);
        }

        private void ShowMenu(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                if (inputFilesListView.FocusedItem.Bounds.Contains(e.Location))
                {
                    menu.Show(Cursor.Position);
                }
            }
        }

        private void UpdateFilePropPrediction(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            var info = new MkvFileInfo();
            var file = info.GetAttributes(e.Item.Name);
            flowLayoutPanel1.Controls.Clear();
            flowLayoutPanel1.Invalidate();

            var titleLabel = new Label
            {
                Parent = flowLayoutPanel1,
                Text = @"Current Title: " + file.SegementInformation?.Title,
                AutoSize = true
            };

            flowLayoutPanel1.Container?.Add(titleLabel);

            var videoTrackNumber = 1;
            var audioTrackNumber = 1;
            var subtitleTrackNumber = 1;

            foreach (var fileTrack in file.Tracks)
            {
                if (fileTrack.Type == MkvTrack.TrackType.Video)
                {
                    var nameLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:v" + videoTrackNumber + @" Name: " + fileTrack.Name,
                        Parent = flowLayoutPanel1
                    };

                    var languageLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:v" + videoTrackNumber + @" Language: " + fileTrack.Language,
                        Parent = flowLayoutPanel1
                    };
                    videoTrackNumber++;
                    if (flowLayoutPanel1.Container != null)
                    {
                        flowLayoutPanel1.Container.Add(nameLabel);
                        flowLayoutPanel1.Container.Add(languageLabel);
                    }
                }

                if (fileTrack.Type == MkvTrack.TrackType.Audio)
                {
                    var nameLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:a" + audioTrackNumber + @" Name: " + fileTrack.Name,
                        Parent = flowLayoutPanel1
                    };
                    var languageLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:a" + audioTrackNumber + @" Language: " + fileTrack.Language,
                        Parent = flowLayoutPanel1
                    };
                    audioTrackNumber++;
                    if (flowLayoutPanel1.Container != null)
                    {
                        flowLayoutPanel1.Container.Add(nameLabel);
                        flowLayoutPanel1.Container.Add(languageLabel);
                    }
                }

                if (fileTrack.Type == MkvTrack.TrackType.Subtitle)
                {
                    var nameLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:s" + subtitleTrackNumber + @" Name: " + fileTrack.Name,
                        Parent = flowLayoutPanel1
                    };
                    var languageLabel = new Label
                    {
                        AutoSize = true,
                        Text = @"Track:s" + subtitleTrackNumber + @" Language: " + fileTrack.Language,
                        Parent = flowLayoutPanel1
                    };
                    subtitleTrackNumber++;
                    if (flowLayoutPanel1.Container != null)
                    {
                        flowLayoutPanel1.Container.Add(nameLabel);
                        flowLayoutPanel1.Container.Add(languageLabel);
                    }
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private string GetEpisodeName(string text)
        {
            var s = new StringBuilder();
            var hyphenCount = 0;
            var index = 0;
            var fileExtensionStartPoint = text.LastIndexOf(".", StringComparison.InvariantCulture);
            foreach (var c in text)
            {
                if (c == '-' && hyphenCount != 2)
                {
                    hyphenCount++;
                    index++;
                    continue;
                }

                if (hyphenCount == 2)
                {
                    if (c == '.' && index == fileExtensionStartPoint)
                    {
                        break;
                    }
                    s.Append(c);
                }

                index++;
            }

            return s.ToString().Trim();
        }

        private void ListFiles(string folderPath)
        {
            var dir = new DirectoryInfo(folderPath);
            var files = dir.GetFiles("*.mkv", SearchOption.TopDirectoryOnly);
            foreach (var file in files)
            {
                var node = new ListViewItem
                {
                    Tag = true,         //Assume the file needs to be updated.
                    Name = file.FullName,
                    Text = file.Name
                };
                inputFilesListView.Items.Add(node);
            }

            if (inputFilesListView.Items.Count > 0)
            {
                applyChangesButton.Enabled = true;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var d = new FolderBrowserDialog();
            if (d.ShowDialog() != DialogResult.OK) return;
            ClearForm();
            ListFiles(d.SelectedPath);
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            inputFilesListView.Columns[0].Width = inputFilesListView.Width - 10;
        }

        private void applyChangesButton_Click(object sender, EventArgs e)
        {

            foreach (ListViewItem node in inputFilesListView.Items)
            {
                //Check to see if the item has been modified.
                if (node.Tag == null || (bool) node.Tag == false) continue;
                if (!File.Exists(node.Name)) continue;
                var command = "/C mkvpropedit.exe --edit info --set \"title=" + GetEpisodeName(node.Text) +
                              "\" --edit track:v1 --set \"name=" + GetEpisodeName(node.Text) +
                              "\" --edit track:v1 --set \"language=eng\" --edit track:a1 --set \"name=English\" --edit track:a1 --set \"language=eng\" \"" + node.Name + "\" > temp.txt";
                var process = new Process();
                var startInfo = new ProcessStartInfo
                {
                    WindowStyle = ProcessWindowStyle.Normal,
                    FileName = "cmd.exe",
                    Arguments = command
                };
                process.StartInfo = startInfo;
                process.Start();
                while (!process.HasExited)
                {

                }
                if (process.ExitCode == 0) continue;
                var error = File.ReadAllLines("temp.txt");
                MessageBox.Show(@"Error on node: " + node.Text + (error.Length > 0 ? Environment.NewLine + error[0] : string.Empty));
                break;
            }

            File.Delete("temp.txt");
        }

        private void ClearForm()
        {
            inputFilesListView.Items.Clear();
            flowLayoutPanel1.Controls.Clear();
            flowLayoutPanel1.Invalidate();
        }

        private void openFolderFileMainMenu_Click(object sender, EventArgs e)
        {
            var d = new FolderBrowserDialog();
            if (d.ShowDialog() != DialogResult.OK) return;
            ClearForm();
            ListFiles(d.SelectedPath);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e) => Application.Exit();

        public static bool CheckFiles()
        {
            return File.Exists("mkvpropedit.exe") && File.Exists("mkvinfo.exe");
        }

        private void ReadXml(string s)
        {
            var xReader = new XmlTextReader(new StringReader(s));
            var r = new StringBuilder();
            ClearForm();
            var tags = new List<XmlTag>();
            while (xReader.Read())
            {
                switch (xReader.NodeType)
                {
                    case XmlNodeType.Element:
                        //inputFilesListView.Items.Add(xReader.Name + ": " + xReader.Value);
                        var t = new XmlTag
                        {
                            Name = xReader.Name
                        };
                        tags.Add(t);
                        break;
                    case XmlNodeType.Text:
                        //inputFilesListView.Items.Add(xReader.Value);
                        tags[tags.Count - 1].Value = xReader.Value;
                        break;
                }
            }

            foreach (var tag in tags)
            {
                var label = new Label
                {
                    Text = tag.Name
                };
                var textBox = new TextBox
                {
                    Text = tag.Value
                };
                if (flowLayoutPanel1.Container != null)
                {
                    flowLayoutPanel1.Container.Add(label);
                    flowLayoutPanel1.Container.Add(textBox);
                }
                //inputFilesListView.Items.Add(tag.Name + ": " + tag.Value);
            }
        }

        private void debugToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //var xml = new SerializeMkvInfo();
            //var x = xml.SerializeFile("info.txt");
            //var text = new StringBuilder();
            //foreach (var line in x)
            //{
            //    text.Append(line.Trim());
            //}
            //ReadXml(text.ToString());
            var p = new FrmProperties();
            p.ShowDialog();
        }
    }
}
