using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MKVTest
{
    internal class SerializeMkvInfo
    {

        public List<String> SerializeFile(string filePath)
        {
            var file = File.ReadAllLines(filePath);
            if (file.Length == 0) return new List<string>();
            var lastDepthLevel = 0;
            var xml = new StringBuilder();
            var stack = new Stack<XmlTag>();
            var test = new List<string>();
            for (var i = 0; i < file.Length; i++)
            {
                var depth = GetDepth(file[i]);
                var tag = CreateTagFromString(file[i]);
                var padding = new StringBuilder();
                for (var j = depth; j != 0; j--)
                {
                    padding.Append(" ");
                }
                
                //xml.Append(padding + "<" + tag.Name + ">" + tag.Value == string.Empty ? Environment.NewLine : string.Empty);
                test.Add(padding + "<" + tag.Name + ">");
                //if (stack.Count != 0)
                //{
                //    var t = stack.Pop();
                //    //xml.Append(t.Value + "</" + t.Name + ">");
                //    test.Add(t.Value + "</" + t.Name + ">");
                //}
                if (depth == lastDepthLevel)
                {
                    if (stack.Count != 0)
                    {
                        if (!string.IsNullOrEmpty(stack.Peek().Value))
                        {
                            var t = stack.Pop();
                            //xml.Append(t.Value + "</" + t.Name + ">");
                            test[test.Count - 1] = test[test.Count - 1] + (tag.Value + "</") + tag.Name + ">";
                            continue;
                        }
                        else
                        {
                            var t = stack.Pop();
                            test.Insert(i, padding + "</" + t.Name + ">");
                        }
                    }

                    //xml.Append("<" + tag.Name + ">");
                    //test.Add("<" + tag.Name + ">");
                }
                else if (depth < lastDepthLevel)
                {
                    //Moving up
                    if (stack.Count != 0)
                    {
                        var t = stack.Pop();
                        //xml.Append(t.Value + "</" + t.Name + ">");
                        test[test.Count - 1] = test[test.Count - 1] + (tag.Value + "</") + tag.Name + ">";
                        continue;
                    }

                }
                else
                {
                    if (stack.Count != 0 && i != 0)
                    {
                        if (!string.IsNullOrEmpty(stack.Peek().Value))
                        {
                            var t = stack.Pop();
                            //xml.Append(t.Value + "</" + t.Name + ">");
                            test.Add(t.Value + "</" + t.Name + ">");
                        }
                        test[test.Count - 1] = test[test.Count - 1] + (tag.Value + "</") + tag.Name + ">";
                        continue;
                    }
                }
                stack.Push(tag);
                lastDepthLevel = depth;
            }

            
            return test;
        }

        private XmlTag CreateTagFromString(string text, XmlTag parent = null)
        {
            var tag = new XmlTag();
            var clearingPadding = true;
            var foundDelimiter = false;
            var name = new StringBuilder();
            var value = new StringBuilder();

            for (var i = 0; i < text.Length; i++)
            {
                if ((char.IsSymbol(text[i]) || char.IsPunctuation(text[i]) || char.IsWhiteSpace(text[i])) && clearingPadding)
                {
                    continue;
                }

                if (text[i].ToString() == ":" && !foundDelimiter)
                {
                    foundDelimiter = true;
                    continue;
                }
                
                clearingPadding = false;
                if (foundDelimiter)
                {
                    value.Append(text[i]);
                }
                else
                {
                    name.Append(text[i]);
                }
            }

            tag.Name = FormatTagName(name.ToString());
            tag.Value = value.ToString().Trim();
            tag.Parent = parent;

            return tag;
        }

        private string FormatTagName(string text)
        {
            var name = new StringBuilder();
            var previousCharWasWhiteSpace = false;

            foreach (var c in text)
            {
                if (!char.IsWhiteSpace(c))
                {
                    name.Append(previousCharWasWhiteSpace ? char.ToUpper(c) : c);
                    previousCharWasWhiteSpace = false;
                }

                if (char.IsWhiteSpace(c))
                {
                    previousCharWasWhiteSpace = true;
                }
            }

            return name.ToString();
        }

        private int GetDepth(string line)
        {
            var depth = 0;

            for (var i = 0; i < line.Length; i++)
            {
                if (char.IsPunctuation(line[i]) || char.IsWhiteSpace(line[i]) || char.IsSymbol(line[i]))
                {
                    depth++;
                }
                else
                {
                    break;
                }
            }

            return depth;
        }

        private bool IsClusterHead(string data)
        {
            var isClusterHeader = false;

            switch (data)
            {
                case "EBML head":

                    break;
                case "Chapters":

                    break;
                case "Segment":

                    break;
                case "Segment information":

                    break;
                case "Segment tracks":

                    break;
                case "A track":

                    break;
                case "Video track":

                    break;
                case "Audio track":

                    break;
            }

            return isClusterHeader;
        }
    }
}
