using System;
using System.Collections.Generic;

namespace Spectre.Console.Internal
{
    internal static class MarkupParser
    {
        public static IMarkupNode Parse(string text)
        {
            using var tokenizer = new MarkupTokenizer(text);
            var root = new MarkupBlockNode();

            var stack = new Stack<MarkupBlockNode>();
            var current = root;

            while (true)
            {
                var token = tokenizer.GetNext();
                if (token == null)
                {
                    break;
                }

                if (token.Kind == MarkupTokenKind.Text)
                {
                    current.Append(new MarkupTextNode(token.Value));
                    continue;
                }
                else if (token.Kind == MarkupTokenKind.Open)
                {
                    var (style, foreground, background) = MarkupStyleParser.Parse(token.Value);
                    var content = new MarkupBlockNode();
                    current.Append(new MarkupStyleNode(style, foreground, background, content));

                    current = content;
                    stack.Push(current);

                    continue;
                }
                else if (token.Kind == MarkupTokenKind.Close)
                {
                    if (stack.Count == 0)
                    {
                        throw new InvalidOperationException($"Encountered closing tag when none was expected near position {token.Position}.");
                    }

                    stack.Pop();

                    if (stack.Count == 0)
                    {
                        current = root;
                    }
                    else
                    {
                        current = stack.Peek();
                    }

                    continue;
                }

                throw new InvalidOperationException("Encountered unkown markup token.");
            }

            if (stack.Count > 0)
            {
                throw new InvalidOperationException("Unbalanced markup stack. Did you forget to close a tag?");
            }

            return root;
        }
    }
}