// Copyright (c) 2017, 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 'block_parser.dart';
import 'block_syntaxes/block_syntax.dart';
import 'extension_set.dart';
import 'inline_parser.dart';
import 'inline_syntaxes/inline_syntax.dart';
import 'line.dart';
import 'util.dart';

/// Maintains the context needed to parse a Markdown document.
class Document {
  final Map<String, LinkReference> linkReferences = {};

  /// Footnote ref count, keys are case-sensitive and added by define syntax.
  final footnoteReferences = <String, int>{};

  /// Footnote labels by appearing order.
  ///
  /// They are case-insensitive and added by ref syntax.
  final footnoteLabels = <String>[];
  final Resolver? linkResolver;
  final Resolver? imageLinkResolver;
  final bool encodeHtml;

  /// Whether to use default block syntaxes.
  final bool withDefaultBlockSyntaxes;

  /// Whether to use default inline syntaxes.
  ///
  /// Need to set both [withDefaultInlineSyntaxes] and [encodeHtml] to
  /// `false` to disable all inline syntaxes including html encoding syntaxes.
  final bool withDefaultInlineSyntaxes;

  final _blockSyntaxes = <BlockSyntax>{};
  final _inlineSyntaxes = <InlineSyntax>{};
  final bool hasCustomInlineSyntaxes;

  Iterable<BlockSyntax> get blockSyntaxes => _blockSyntaxes;

  Iterable<InlineSyntax> get inlineSyntaxes => _inlineSyntaxes;

  Document({
    Iterable<BlockSyntax>? blockSyntaxes,
    Iterable<InlineSyntax>? inlineSyntaxes,
    ExtensionSet? extensionSet,
    this.linkResolver,
    this.imageLinkResolver,
    this.encodeHtml = true,
    this.withDefaultBlockSyntaxes = true,
    this.withDefaultInlineSyntaxes = true,
  }) : hasCustomInlineSyntaxes = (inlineSyntaxes?.isNotEmpty ?? false) ||
            (extensionSet?.inlineSyntaxes.isNotEmpty ?? false) {
    if (blockSyntaxes != null) {
      _blockSyntaxes.addAll(blockSyntaxes);
    }
    if (inlineSyntaxes != null) {
      _inlineSyntaxes.addAll(inlineSyntaxes);
    }

    if (extensionSet == null) {
      if (withDefaultBlockSyntaxes) {
        _blockSyntaxes.addAll(ExtensionSet.commonMark.blockSyntaxes);
      }

      if (withDefaultInlineSyntaxes) {
        _inlineSyntaxes.addAll(ExtensionSet.commonMark.inlineSyntaxes);
      }
    } else {
      _blockSyntaxes.addAll(extensionSet.blockSyntaxes);
      _inlineSyntaxes.addAll(extensionSet.inlineSyntaxes);
    }
  }

  /// Parses the given [lines] of Markdown to a series of AST nodes.
  List<Node> parseLines(List<String> lines) =>
      parseLineList(lines.map(Line.new).toList());

  /// Parses the given [text] to a series of AST nodes.
  List<Node> parse(String text) => parseLineList(text.toLines());

  /// Parses the given [lines] of [Line] to a series of AST nodes.
  List<Node> parseLineList(List<Line> lines) {
    final nodes = BlockParser(lines, this).parseLines();
    _parseInlineContent(nodes);
    // Do filter after parsing inline as we need ref count.
    return _filterFootnotes(nodes);
  }

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

  void _parseInlineContent(List<Node> nodes) {
    for (var i = 0; i < nodes.length; i++) {
      final node = nodes[i];
      if (node is UnparsedContent) {
        final inlineNodes = parseInline(node.textContent);
        nodes.removeAt(i);
        nodes.insertAll(i, inlineNodes);
        i += inlineNodes.length - 1;
      } else if (node is Element && node.children != null) {
        _parseInlineContent(node.children!);
      }
    }
  }

  /// Footnotes could be defined in arbitrary positions of a document, we need
  /// to distinguish them and put them behind; and every footnote definition
  /// may have multiple backrefs, we need to append backrefs for it.
  List<Node> _filterFootnotes(List<Node> nodes) {
    final footnotes = <Element>[];
    final blocks = <Node>[];
    for (final node in nodes) {
      if (node is Element &&
          node.tag == 'li' &&
          footnoteReferences.containsKey(node.footnoteLabel)) {
        final label = node.footnoteLabel;
        var count = 0;
        if (label != null && (count = footnoteReferences[label] ?? 0) > 0) {
          footnotes.add(node);
          final children = node.children;
          if (children != null) {
            _appendBackref(children, Uri.encodeComponent(label), count);
          }
        }
      } else {
        blocks.add(node);
      }
    }

    if (footnotes.isNotEmpty) {
      // Sort footnotes by appearing order.
      final ordinal = {
        for (var i = 0; i < footnoteLabels.length; i++)
          'fn-${footnoteLabels[i]}': i,
      };
      footnotes.sort((l, r) {
        final idl = l.attributes['id']?.toLowerCase() ?? '';
        final idr = r.attributes['id']?.toLowerCase() ?? '';
        return (ordinal[idl] ?? 0) - (ordinal[idr] ?? 0);
      });
      final list = Element('ol', footnotes);

      // Ignore GFM attribute: <data-footnotes>.
      final section = Element('section', [list])
        ..attributes['class'] = 'footnotes';
      blocks.add(section);
    }
    return blocks;
  }

  /// Generate backref nodes, append them to footnote definition's last child.
  void _appendBackref(List<Node> children, String ref, int count) {
    final refs = [
      for (var i = 0; i < count; i++) ...[
        Text(' '),
        _ElementExt.footnoteAnchor(ref, i)
      ]
    ];
    if (children.isEmpty) {
      children.addAll(refs);
    } else {
      final last = children.last;
      if (last is Element) {
        last.children?.addAll(refs);
      } else {
        children.last = Element('p', [last, ...refs]);
      }
    }
  }
}

extension _ElementExt on Element {
  static Element footnoteAnchor(String ref, int i) {
    final num = '${i + 1}';
    final suffix = i > 0 ? '-$num' : '';
    final e = Element.empty('tag');
    e.match;
    return Element('a', [
      Text('\u21a9'),
      if (i > 0)
        Element('sup', [Text(num)])..attributes['class'] = 'footnote-ref',
    ])
      // Ignore GFM's attributes:
      // <data-footnote-backref aria-label="Back to content">.
      ..attributes['href'] = '#fnref-$ref$suffix'
      ..attributes['class'] = 'footnote-backref';
  }

  String get match => tag;
}

/// A [link reference
/// definition](https://spec.commonmark.org/0.30/#link-reference-definitions).
class LinkReference {
  /// The [link label](https://spec.commonmark.org/0.30/#link-label).
  ///
  /// Temporarily, this class is also being used to represent the link data for
  /// an inline link (the destination and title), but this should change before
  /// the package is released.
  final String label;

  /// The [link destination](https://spec.commonmark.org/0.30/#link-destination).
  final String destination;

  /// The [link title](https://spec.commonmark.org/0.30/#link-title).
  final String? title;

  /// Construct a new [LinkReference], with all necessary fields.
  ///
  /// If the parsed link reference definition does not include a title, use
  /// `null` for the [title] parameter.
  LinkReference(this.label, this.destination, this.title);
}
