library markdown.src.document;

import 'ast.dart';
import 'block_parser.dart';
import 'extension_set.dart';
import 'inline_parser.dart';

/// Maintains the context needed to parse a Markdown document.
class Document {
  final Map<String, Link> refLinks = {};
  Iterable<BlockSyntax> blockSyntaxes;
  Iterable<InlineSyntax> inlineSyntaxes;
  ExtensionSet extensionSet;
  Resolver linkResolver;
  Resolver imageLinkResolver;

  Document(
      {Iterable<BlockSyntax> blockSyntaxes,
      Iterable<InlineSyntax> inlineSyntaxes,
      ExtensionSet extensionSet,
      this.linkResolver,
      this.imageLinkResolver}) {
    this.extensionSet = extensionSet ?? ExtensionSet.commonMark;
    this.blockSyntaxes = new Set()
      ..addAll(blockSyntaxes ?? [])
      ..addAll(this.extensionSet.blockSyntaxes);
    this.inlineSyntaxes = new Set()
      ..addAll(inlineSyntaxes ?? [])
      ..addAll(this.extensionSet.inlineSyntaxes);
  }

  /// Parses [lines] for reference links, adding them to [refLinks] and
  /// replaces their source lines with blank lines.
  parseRefLinks(List<String> lines) {
    // This is a hideous regex. It matches:
    // [id]: http:foo.com "some title"
    // Where there may whitespace in there, and where the title may be in
    // single quotes, double quotes, or parentheses.
    var indent = r'^[ ]{0,3}'; // Leading indentation.
    var id = r'\[([^\]]+)\]'; // Reference id in [brackets].
    var quote = r'"[^"]+"'; // Title in "double quotes".
    var apos = r"'[^']+'"; // Title in 'single quotes'.
    var paren = r"\([^)]+\)"; // Title in (parentheses).
    var pattern =
        new RegExp('$indent$id:\\s+(\\S+)\\s*($quote|$apos|$paren|)\\s*\$');

    for (var i = 0; i < lines.length; i++) {
      var match = pattern.firstMatch(lines[i]);
      if (match != null) {
        // Parse the link.
        var id = match[1];
        var url = match[2];
        var title = match[3];

        if (title == '') {
          // No title.
          title = null;
        } else {
          // Remove "", '', or ().
          title = title.substring(1, title.length - 1);
        }

        // References are case-insensitive.
        id = id.toLowerCase();

        refLinks[id] = new Link(id, url, title);

        // Remove it from the output. We replace it with a blank line which will
        // get consumed by later processing.
        lines[i] = '';
      }
    }
  }

  /// Parses the given [lines] of Markdown to a series of AST nodes.
  List<Node> parseLines(List<String> lines) {
    var parser = new BlockParser(lines, this);

    var blocks = <Node>[];
    while (!parser.isDone) {
      for (var syntax in parser.blockSyntaxes) {
        if (syntax.canParse(parser)) {
          var block = syntax.parse(parser);
          if (block != null) blocks.add(block);
          break;
        }
      }
    }

    return blocks;
  }

  /// Parses the given inline Markdown [text] to a series of AST nodes.
  List<Node> parseInline(String text) => new InlineParser(text, this).parse();
}

class Link {
  final String id;
  final String url;
  final String title;
  Link(this.id, this.url, this.title);
}
