// Copyright (c) 2019, 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.

/// Information about the directives found in Dartdoc comments.
class DartdocDirectiveInfo {
  // TODO(brianwilkerson) Consider moving the method
  //  DartUnitHoverComputer.computeDocumentation to this class.

  /// A regular expression used to match a macro directive. There is one group
  /// that contains the name of the template.
  static final macroRegExp = RegExp(r'{@macro\s+([^}]+)}');

  /// A regular expression used to match a template directive. There are two
  /// groups. The first contains the name of the template, the second contains
  /// the body of the template.
  static final templateRegExp = RegExp(
      r'[ ]*{@template\s+(.+?)}([\s\S]+?){@endtemplate}[ ]*\n?',
      multiLine: true);

  /// A regular expression used to match a youtube or animation directive.
  ///
  /// These are in the form:
  /// `{@youtube 560 315 https://www.youtube.com/watch?v=2uaoEDOgk_I}`.
  static final videoRegExp =
      RegExp(r'{@(youtube|animation)\s+[^}]+\s+[^}]+\s+([^}]+)}');

  /// A table mapping the names of templates to the unprocessed bodies of the
  /// templates.
  final Map<String, String> templateMap = {};

  /// Initialize a newly created set of information about Dartdoc directives.
  DartdocDirectiveInfo();

  /// Add corresponding pairs from the [names] and [values] to the set of
  /// defined templates.
  void addTemplateNamesAndValues(List<String> names, List<String> values) {
    int length = names.length;
    assert(length == values.length);
    for (int i = 0; i < length; i++) {
      templateMap[names[i]] = values[i];
    }
  }

  /// Process the given Dartdoc [comment], extracting the template directive if
  /// there is one.
  void extractTemplate(String? comment) {
    if (comment == null) return;

    for (Match match in templateRegExp.allMatches(comment)) {
      String name = match.group(1)!.trim();
      String body = match.group(2)!.trim();
      templateMap[name] = _stripDelimiters(body).join('\n');
    }
  }

  /// Process the given Dartdoc [comment], replacing any known dartdoc
  /// directives with the associated content.
  ///
  /// Macro directives are replaced with the body of the corresponding template.
  ///
  /// Youtube and animation directives are replaced with markdown hyperlinks.
  Documentation processDartdoc(String comment, {bool includeSummary = false}) {
    List<String> lines = _stripDelimiters(comment);
    var firstBlankLine = lines.length;
    for (int i = lines.length - 1; i >= 0; i--) {
      String line = lines[i];
      if (line.isEmpty) {
        // Because we're iterating from the last line to the first, the last
        // blank line we find is the first.
        firstBlankLine = i;
      } else {
        var match = macroRegExp.firstMatch(line);
        if (match != null) {
          var name = match.group(1)!;
          var value = templateMap[name];
          if (value != null) {
            lines[i] = value;
          }
          continue;
        }

        match = videoRegExp.firstMatch(line);
        if (match != null) {
          var uri = match.group(2);
          if (uri != null && uri.isNotEmpty) {
            String label = uri;
            if (label.startsWith('https://')) {
              label = label.substring('https://'.length);
            }
            lines[i] = '[$label]($uri)';
          }
          continue;
        }
      }
    }
    if (includeSummary) {
      var full = lines.join('\n');
      var summary = firstBlankLine == lines.length
          ? full
          : lines.getRange(0, firstBlankLine).join('\n').trim();
      return DocumentationWithSummary(full: full, summary: summary);
    }
    return Documentation(full: lines.join('\n'));
  }

  bool _isWhitespace(String comment, int index, bool includeEol) {
    if (comment.startsWith(' ', index) ||
        comment.startsWith('\t', index) ||
        (includeEol && comment.startsWith('\n', index))) {
      return true;
    }
    return false;
  }

  int _skipWhitespaceBackward(String comment, int start, int end,
      [bool skipEol = false]) {
    while (start < end && _isWhitespace(comment, end, skipEol)) {
      end--;
    }
    return end;
  }

  int _skipWhitespaceForward(String comment, int start, int end,
      [bool skipEol = false]) {
    while (start < end && _isWhitespace(comment, start, skipEol)) {
      start++;
    }
    return start;
  }

  /// Remove the delimiters from the given [comment].
  List<String> _stripDelimiters(String comment) {
    var start = 0;
    var end = comment.length;
    if (comment.startsWith('/**')) {
      start = _skipWhitespaceForward(comment, 3, end, true);
      if (comment.endsWith('*/')) {
        end = _skipWhitespaceBackward(comment, start, end - 2, true);
      }
    }
    var line = -1;
    var firstNonEmpty = -1;
    var lastNonEmpty = -1;
    var lines = <String>[];
    while (start < end) {
      line++;
      var eolIndex = comment.indexOf('\n', start);
      if (eolIndex < 0) {
        eolIndex = end;
      }
      var lineStart = _skipWhitespaceForward(comment, start, eolIndex);
      if (comment.startsWith('///', lineStart)) {
        lineStart += 3;
        if (_isWhitespace(comment, lineStart, false)) {
          lineStart++;
        }
      } else if (comment.startsWith('*', lineStart)) {
        lineStart += 1;
        if (_isWhitespace(comment, lineStart, false)) {
          lineStart++;
        }
      }
      var lineEnd =
          _skipWhitespaceBackward(comment, lineStart, eolIndex - 1) + 1;
      if (lineStart < lineEnd) {
        // If the line is not empty, update the line range.
        if (firstNonEmpty < 0) {
          firstNonEmpty = line;
        }
        if (line > lastNonEmpty) {
          lastNonEmpty = line;
        }
        lines.add(comment.substring(lineStart, lineEnd));
      } else {
        lines.add('');
      }
      start = eolIndex + 1;
    }
    if (firstNonEmpty < 0 || lastNonEmpty < firstNonEmpty) {
      // All of the lines are empty.
      return const <String>[];
    }
    return lines.sublist(firstNonEmpty, lastNonEmpty + 1);
  }
}

/// A representation of the documentation for an element.
class Documentation {
  String full;

  Documentation({required this.full});
}

/// A representation of the documentation for an element that includes a
/// summary.
class DocumentationWithSummary extends Documentation {
  final String summary;

  DocumentationWithSummary({required String full, required this.summary})
      : super(full: full);
}
