// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'ast.dart';
import 'charcode.dart';
import 'document.dart';
import 'inline_syntaxes/autolink_syntax.dart';
import 'inline_syntaxes/code_syntax.dart';
import 'inline_syntaxes/decode_html_syntax.dart';
import 'inline_syntaxes/delimiter_syntax.dart';
import 'inline_syntaxes/email_autolink_syntax.dart';
import 'inline_syntaxes/emphasis_syntax.dart';
import 'inline_syntaxes/escape_syntax.dart';
import 'inline_syntaxes/image_syntax.dart';
import 'inline_syntaxes/inline_syntax.dart';
import 'inline_syntaxes/line_break_syntax.dart';
import 'inline_syntaxes/link_syntax.dart';
import 'inline_syntaxes/soft_line_break_syntax.dart';
import 'inline_syntaxes/text_syntax.dart';

/// Maintains the internal state needed to parse inline span elements in
/// Markdown.
class InlineParser {
  static final List<InlineSyntax> _defaultSyntaxes =
      List<InlineSyntax>.unmodifiable(<InlineSyntax>[
    EmailAutolinkSyntax(),
    AutolinkSyntax(),
    LineBreakSyntax(),
    // Allow any punctuation to be escaped.
    EscapeSyntax(),
    // "*" surrounded by spaces is left alone.
    TextSyntax(r' \* ', startCharacter: $space),
    // "_" surrounded by spaces is left alone.
    TextSyntax(' _ ', startCharacter: $space),
    // Parse "**strong**" and "*emphasis*" tags.
    EmphasisSyntax.asterisk(),
    // Parse "__strong__" and "_emphasis_" tags.
    EmphasisSyntax.underscore(),
    CodeSyntax(),
    SoftLineBreakSyntax(),
    // We will add the LinkSyntax once we know about the specific link resolver.
  ]);

  static final List<InlineSyntax> _htmlSyntaxes =
      List<InlineSyntax>.unmodifiable(<InlineSyntax>[
    // Leave already-encoded HTML entities alone. Ensures we don't turn
    // "&amp;" into "&amp;amp;"
    TextSyntax('&[#a-zA-Z0-9]*;', startCharacter: $ampersand),
    // Encode "&".
    TextSyntax('&', sub: '&amp;', startCharacter: $ampersand),
    // Encode "<".
    TextSyntax('<', sub: '&lt;', startCharacter: $lt),
    // Encode ">".
    TextSyntax('>', sub: '&gt;', startCharacter: $gt),
  ]);

  /// The string of Markdown being parsed.
  final String source;

  /// The Markdown document this parser is parsing.
  final Document document;

  final List<InlineSyntax> syntaxes = <InlineSyntax>[];

  /// The current read position.
  int pos = 0;

  /// Starting position of the last unconsumed text.
  int start = 0;

  /// The delimiter stack tracking possible opening delimiters and closing
  /// delimiters for [DelimiterSyntax] nodes.
  final _delimiterStack = <Delimiter>[];

  /// The tree of parsed HTML nodes.
  final _tree = <Node>[];

  InlineParser(this.source, this.document) {
    // User specified syntaxes are the first syntaxes to be evaluated.
    syntaxes.addAll(document.inlineSyntaxes);

    // This first RegExp matches plain text to accelerate parsing. It's written
    // so that it does not match any prefix of any following syntaxes. Most
    // Markdown is plain text, so it's faster to match one RegExp per 'word'
    // rather than fail to match all the following RegExps at each non-syntax
    // character position.
    if (document.hasCustomInlineSyntaxes) {
      // We should be less aggressive in blowing past "words".
      syntaxes.add(TextSyntax(r'[A-Za-z0-9]+(?=\s)'));
    } else {
      syntaxes.add(TextSyntax(r'[ \tA-Za-z0-9]*[A-Za-z0-9](?=\s)'));
    }

    if (document.withDefaultInlineSyntaxes) {
      // Custom link resolvers go after the generic text syntax.
      syntaxes.addAll([
        DecodeHtmlSyntax(),
        LinkSyntax(linkResolver: document.linkResolver),
        ImageSyntax(linkResolver: document.imageLinkResolver)
      ]);

      syntaxes.addAll(_defaultSyntaxes);
    }

    if (encodeHtml) {
      syntaxes.addAll(_htmlSyntaxes);
    }
  }

  List<Node> parse() {
    while (!isDone) {
      // A right bracket (']') is special. Hitting this character triggers the
      // "look for link or image" procedure.
      // See https://spec.commonmark.org/0.29/#an-algorithm-for-parsing-nested-emphasis-and-links.
      if (charAt(pos) == $rbracket) {
        writeText();
        _linkOrImage();
        continue;
      }

      // See if the current text matches any defined Markdown syntax.
      if (syntaxes.any((syntax) => syntax.tryMatch(this))) continue;

      // If we got here, it's just text.
      advanceBy(1);
    }

    // Write any trailing text content to a Text node.
    writeText();
    _processDelimiterRun(-1);
    _combineAdjacentText(_tree);
    return _tree;
  }

  /// Look back through the delimiter stack to see if we've found a link or
  /// image.
  ///
  /// This is the "look for link or image" routine from the CommonMark spec:
  /// https://spec.commonmark.org/0.29/#-look-for-link-or-image-.
  void _linkOrImage() {
    final index = _delimiterStack
        .lastIndexWhere((d) => d.char == $lbracket || d.char == $exclamation);
    if (index == -1) {
      // Never found a possible open bracket. This is just a literal "]".
      addNode(Text(']'));
      advanceBy(1);
      start = pos;
      return;
    }
    final delimiter = _delimiterStack[index] as SimpleDelimiter;
    if (!delimiter.isActive) {
      _delimiterStack.removeAt(index);
      addNode(Text(']'));
      advanceBy(1);
      start = pos;
      return;
    }
    final syntax = delimiter.syntax;
    if (syntax is LinkSyntax && syntaxes.any((e) => e is LinkSyntax)) {
      final nodeIndex = _tree.lastIndexWhere((n) => n == delimiter.node);
      final linkNodes = syntax.close(this, delimiter, null, getChildren: () {
        _processDelimiterRun(index);
        // All of the nodes which lie past [index] are children of this
        // link/image.
        final children = _tree.sublist(nodeIndex + 1, _tree.length);
        _tree.removeRange(nodeIndex + 1, _tree.length);
        return children;
      });
      if (linkNodes != null) {
        _delimiterStack.removeAt(index);
        if (delimiter.char == $lbracket) {
          for (final d in _delimiterStack.sublist(0, index)) {
            if (d.char == $lbracket) d.isActive = false;
          }
        }
        _tree.replaceRange(nodeIndex, _tree.length, linkNodes);
        advanceBy(1);
        start = pos;
      } else {
        _delimiterStack.removeAt(index);
        pos = start;
        advanceBy(1);
      }
    } else {
      throw StateError('Non-link syntax delimiter found with character '
          '"${delimiter.char}"');
    }
  }

  /// Rules 9 and 10.
  bool _canFormEmphasis(Delimiter opener, Delimiter closer) {
    if ((opener.canOpen && opener.canClose) ||
        (closer.canOpen && closer.canClose)) {
      return (opener.length + closer.length) % 3 != 0 ||
          (opener.length % 3 == 0 && closer.length % 3 == 0);
    } else {
      return true;
    }
  }

  /// Processes [DelimiterRun] type delimiters from [bottomIndex] and up.
  ///
  /// This is the same strategy as "process emphasis" routine according to the
  /// CommonMark spec: https://spec.commonmark.org/0.30/#phase-2-inline-structure.
  void _processDelimiterRun(int bottomIndex) {
    var currentIndex = bottomIndex + 1;
    // Track the lowest index where we might find an open delimiter given a
    // closing delimiter length modulo 3.
    // Each key in this map is an open delimiter character. Each value is a
    // 3-element list. Each value in the list is the lowest index for the given
    // delimiter length modulo 3 (0, 1, 2).
    final openersBottom = <int, List<int>>{};
    while (currentIndex < _delimiterStack.length) {
      final closer = _delimiterStack[currentIndex];
      if (!closer.canClose || closer is! DelimiterRun) {
        currentIndex++;
        continue;
      }
      openersBottom.putIfAbsent(closer.char, () => List.filled(3, bottomIndex));
      final openersBottomPerCloserLength = openersBottom[closer.char]!;
      final openerBottom = openersBottomPerCloserLength[closer.length % 3];
      final openerIndex = _delimiterStack.lastIndexWhere(
          (d) =>
              d.char == closer.char && d.canOpen && _canFormEmphasis(d, closer),
          currentIndex - 1);
      if (openerIndex > bottomIndex && openerIndex > openerBottom) {
        // Found an opener for [closer].
        final opener = _delimiterStack[openerIndex];
        if (opener is! DelimiterRun) {
          currentIndex++;
          continue;
        }
        final matchedTagIndex = opener.tags.lastIndexWhere((e) =>
            opener.length >= e.indicatorLength &&
            closer.length >= e.indicatorLength);
        if (matchedTagIndex == -1) {
          currentIndex++;
          continue;
        }
        final matchedTag = opener.tags[matchedTagIndex];
        final indicatorLength = matchedTag.indicatorLength;
        final openerTextNode = opener.node;
        final openerTextNodeIndex = _tree.indexOf(openerTextNode);
        final closerTextNode = closer.node;
        var closerTextNodeIndex = _tree.indexOf(closerTextNode);
        final nodes = opener.syntax.close(
          this,
          opener,
          closer,
          tag: matchedTag.tag,
          getChildren: () => _tree.sublist(
            openerTextNodeIndex + 1,
            closerTextNodeIndex,
          ),
        );
        // Replace all of the nodes between the opener and the closer (which
        // are now the new emphasis node's children) with the emphasis node.
        _tree.replaceRange(
          openerTextNodeIndex + 1,
          closerTextNodeIndex,
          nodes!,
        );
        // Slide [closerTextNodeIndex] back accordingly.
        closerTextNodeIndex = openerTextNodeIndex + 2;

        _delimiterStack.removeRange(openerIndex + 1, currentIndex);
        // Slide [currentIndex] back accordingly.
        currentIndex = openerIndex + 1;

        // Remove delimiter characters, possibly removing nodes from the tree
        // and Delimiters from the delimiter stack.
        if (opener.length == indicatorLength) {
          _tree.removeAt(openerTextNodeIndex);
          _delimiterStack.removeAt(openerIndex);
          // Slide [currentIndex] and [closerTextNodeIndex] back accordingly.
          currentIndex--;
          closerTextNodeIndex--;
        } else {
          final newOpenerTextNode =
              Text(openerTextNode.text.substring(indicatorLength));
          _tree[openerTextNodeIndex] = newOpenerTextNode;
          opener.node = newOpenerTextNode;
        }

        if (closer.length == indicatorLength) {
          _tree.removeAt(closerTextNodeIndex);
          _delimiterStack.removeAt(currentIndex);
          // [currentIndex] has just moved to point at the next delimiter;
          // leave it.
        } else {
          final newCloserTextNode =
              Text(closerTextNode.text.substring(indicatorLength));
          _tree[closerTextNodeIndex] = newCloserTextNode;
          closer.node = newCloserTextNode;
          // [currentIndex] needs to be considered again; leave it.
        }
      } else {
        // No opener is found.
        openersBottomPerCloserLength[closer.length % 3] = currentIndex - 1;
        if (!closer.canOpen) {
          _delimiterStack.removeAt(currentIndex);
          // This advances [currentIndex] to the next delimiter.
        } else {
          currentIndex++;
        }
      }
    }

    _delimiterStack.removeRange(bottomIndex + 1, _delimiterStack.length);
  }

  // Combine any remaining adjacent Text nodes. This is important to produce
  // correct output across newlines, where whitespace is sometimes compressed.
  void _combineAdjacentText(List<Node> nodes) {
    for (var i = 0; i < nodes.length - 1; i++) {
      final node = nodes[i];
      if (node is Element && node.children != null) {
        _combineAdjacentText(node.children!);
        continue;
      }
      if (node is Text && nodes[i + 1] is Text) {
        final buffer =
            StringBuffer('${node.textContent}${nodes[i + 1].textContent}');
        var j = i + 2;
        while (j < nodes.length && nodes[j] is Text) {
          buffer.write(nodes[j].textContent);
          j++;
        }
        nodes[i] = Text(buffer.toString());
        nodes.removeRange(i + 1, j);
      }
    }
  }

  int charAt(int index) => source.codeUnitAt(index);

  void writeText() {
    if (pos == start) {
      return;
    }
    final text = source.substring(start, pos);
    _tree.add(Text(text));
    start = pos;
  }

  /// Add [node] to the current tree.
  void addNode(Node node) {
    _tree.add(node);
  }

  /// Push [delimiter] onto the stack of [Delimiter]s.
  void pushDelimiter(Delimiter delimiter) => _delimiterStack.add(delimiter);

  bool get isDone => pos == source.length;

  void advanceBy(int length) {
    pos += length;
  }

  void consume(int length) {
    pos += length;
    start = pos;
  }

  bool get encodeHtml => document.encodeHtml;
}
