// Copyright (c) 2018, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';

/// A computer for [CompilationUnit] folding.
class DartUnitFoldingComputer {
  final LineInfo _lineInfo;
  final CompilationUnit _unit;

  _Directive? _firstDirective, _lastDirective;
  final List<FoldingRegion> _foldingRegions = [];

  /// A set of line numbers that already have folding regions defined.
  ///
  /// Multiple regions will not be produced that start on the same line because
  /// editors typically only show one folding action button per line.
  final _linesWithRegions = <int>{};

  new(this._lineInfo, this._unit);

  void addRegionForConditionalBlock(Block block) {
    // For class/function/method blocks, we usually include the whitespace up
    // until the `}` in the folding region so that when collapsed they would
    // look like:
    //
    //    class Foo { [...] }
    //
    // For if/try statements, they may have else/elseIfs which would result in
    // long lines like:
    //
    //     if (cond) { [...] } else { [...] }
    //
    // So these types of blocks should have their folding regions end at the
    // end of the preceding statement.

    var start = block.leftBracket.end;
    Token? comment = block.endToken.precedingComments;
    if (comment != null) {
      var lastComment = comment;
      // If there are comments before the end token, use the last of those.
      var nextComment = lastComment.next;
      while (nextComment != null) {
        lastComment = nextComment;
        nextComment = nextComment.next;
      }
      _addRegion(start, lastComment.end, FoldingKind.BLOCK);
    } else if (block.statements.isNotEmpty) {
      // Otherwise, use the end of the last statement.
      _addRegion(start, block.statements.last.end, FoldingKind.BLOCK);
    }
  }

  /// Returns a list of folding regions, not `null`.
  List<FoldingRegion> compute() {
    _unit.accept(_DartUnitFoldingComputerVisitor(this));

    var firstDirective = _firstDirective;
    var lastDirective = _lastDirective;
    if (firstDirective != null &&
        lastDirective != null &&
        firstDirective != lastDirective) {
      _addRegion(
        firstDirective.keyword.end,
        lastDirective.directive.end,
        FoldingKind.DIRECTIVES,
      );
    }

    _addCommentRegions();

    return _foldingRegions;
  }

  /// Create a folding region for the provided comment, reading forwards if
  /// necessary.
  ///
  /// If [mayBeFileHeader] is true, the token will be considered a file header
  /// if comment is a single-line-comment and there is a blank line or another
  /// comment type after it.
  ///
  /// Returns the next comment to be processed or null if there are no more
  /// comments to process in the chain.
  Token? _addCommentRegion(Token commentToken, {bool mayBeFileHeader = false}) {
    int offset, end;
    var isFileHeader = false;
    Token? nextComment;

    if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
      // Multiline comments already span all of their lines but the folding
      // region should start at the end of the first line.
      offset = commentToken.offset + (commentToken.eolOffset ?? 0);
      end = commentToken.end;
      nextComment = commentToken.next;
    } else {
      // Single line comments need grouping together explicitly but should
      // only group if the prefix is the same and up to any blank line.
      var isTripleSlash = commentToken.isTripleSlash;
      // Track the last comment that belongs to this folding region.
      var lastComment = commentToken;
      var current = lastComment.next;
      while (current != null &&
          current.type == lastComment.type &&
          current.isTripleSlash == isTripleSlash &&
          !_hasBlankLineBetween(lastComment.end, current.offset)) {
        lastComment = current;
        current = current.next;
      }

      // For single line comments we prefer to start the range at the end of
      // first token so the first line is still visible when the range is
      // collapsed.
      offset = commentToken.end;
      end = lastComment.end;
      nextComment = lastComment.next;

      // Single line comments are file headers if they're followed by a different
      // comment type of there's a blank line between them and the first token.
      isFileHeader =
          mayBeFileHeader &&
          (nextComment != null ||
              _hasBlankLineBetween(end, _unit.beginToken.offset));
    }

    var kind = isFileHeader
        ? FoldingKind.FILE_HEADER
        : (commentToken.lexeme.startsWith('///') ||
              commentToken.lexeme.startsWith('/**'))
        ? FoldingKind.DOCUMENTATION_COMMENT
        : FoldingKind.COMMENT;

    _addRegion(offset, end, kind);

    return nextComment;
  }

  void _addCommentRegions() {
    Token? token = _unit.beginToken;
    if (token.type == TokenType.SCRIPT_TAG) {
      token = token.next;
    }
    var isFirstToken = true;
    while (token != null) {
      Token? commentToken = token.precedingComments;
      while (commentToken != null) {
        commentToken = _addCommentRegion(
          commentToken,
          mayBeFileHeader: isFirstToken,
        );
      }
      isFirstToken = false;
      // Only exit the loop when hitting EOF *after* processing the token as
      // the EOF token may have preceding comments.
      if (token.isEof) {
        break;
      }
      token = token.next;
    }
  }

  /// Adds a region from [startOffset] to [endOffset] for [kind].
  ///
  /// If [startOffset] is the same line as a previous range and [fallbackStart]
  /// is provided (and not the same line), then [fallbackStart] will be used.
  void _addRegion(
    int startOffset,
    int endOffset,
    FoldingKind kind, {
    int? fallbackStart,
  }) {
    var start = _lineInfo.getLocation(startOffset);
    var end = _lineInfo.getLocation(endOffset);

    // We cannot start multiple regions on the same line, so if this region
    // starts on the same line as the previous region, try the fallback start.
    //
    // This usually happens with function declarations and parameters, where we
    // want to support folding long parameter lists but also be able to fold the
    // whole declaration (parameters + body).
    if (_linesWithRegions.contains(start.lineNumber)) {
      if (fallbackStart == null) {
        return;
      }

      startOffset = fallbackStart;
      start = _lineInfo.getLocation(startOffset);

      // If it's still the same, then we don't have a usable start.
      if (_linesWithRegions.contains(start.lineNumber)) {
        return;
      }
    }

    if (end.lineNumber > start.lineNumber) {
      _foldingRegions.add(
        FoldingRegion(kind, startOffset, endOffset - startOffset),
      );
      _linesWithRegions.add(start.lineNumber);
    }
  }

  void _addRegionForAnnotations(List<Annotation> annotations) {
    if (annotations.isNotEmpty) {
      _addRegion(
        annotations.first.name.end,
        annotations.last.end,
        FoldingKind.ANNOTATIONS,
      );
    }
  }

  bool _hasBlankLineBetween(int offset, int end) {
    var firstLoc = _lineInfo.getLocation(offset);
    var secondLoc = _lineInfo.getLocation(end);
    return secondLoc.lineNumber - firstLoc.lineNumber > 1;
  }

  void _recordDirective(_Directive node) {
    _firstDirective ??= node;
    _lastDirective = node;
  }
}

/// An AST visitor for [DartUnitFoldingComputer].
class _DartUnitFoldingComputerVisitor extends RecursiveAstVisitor<void> {
  final DartUnitFoldingComputer _computer;

  new(this._computer);

  @override
  void visitArgumentList(ArgumentList node) {
    _computer._addRegion(
      node.leftParenthesis.end,
      node.rightParenthesis.offset,
      FoldingKind.INVOCATION,
      fallbackStart: node.arguments.firstOrNull?.offset,
    );
    super.visitArgumentList(node);
  }

  @override
  void visitAssertInitializer(AssertInitializer node) {
    _computer._addRegion(
      node.leftParenthesis.end,
      node.rightParenthesis.offset,
      FoldingKind.INVOCATION,
      fallbackStart: node.condition.offset,
    );
    super.visitAssertInitializer(node);
  }

  @override
  void visitAssertStatement(AssertStatement node) {
    _computer._addRegion(
      node.leftParenthesis.end,
      node.rightParenthesis.offset,
      FoldingKind.INVOCATION,
    );
    super.visitAssertStatement(node);
  }

  @override
  void visitBlockClassBody(BlockClassBody node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.offset,
      FoldingKind.CLASS_BODY,
    );
    super.visitBlockClassBody(node);
  }

  @override
  void visitBlockEnumBody(BlockEnumBody node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.offset,
      FoldingKind.CLASS_BODY,
    );
    super.visitBlockEnumBody(node);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitClassDeclaration(node);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    // Find the most appropriate place to start.
    // For a named constructor, end of the name.
    // For unnamed constructor, end of the type name.
    // For `new`, end of the keyword.
    var bodyStart =
        node.name?.end ?? node.typeName?.end ?? node.newKeyword?.end;
    if (bodyStart != null) {
      _computer._addRegion(bodyStart, node.end, FoldingKind.FUNCTION_BODY);
    }
    super.visitConstructorDeclaration(node);
  }

  @override
  void visitDoStatement(DoStatement node) {
    var body = node.body;
    if (body is Block) {
      _computer.addRegionForConditionalBlock(body);
    }
    super.visitDoStatement(node);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitEnumDeclaration(node);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    _computer._recordDirective(_Directive(node, node.exportKeyword));
    super.visitExportDirective(node);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitExtensionDeclaration(node);
  }

  @override
  void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitExtensionTypeDeclaration(node);
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitFieldDeclaration(node);
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    _computer._addRegion(
      node.leftParenthesis.end,
      node.rightParenthesis.offset,
      FoldingKind.PARAMETERS,
      fallbackStart: node.parameters.firstOrNull?.offset,
    );
    super.visitFormalParameterList(node);
  }

  @override
  void visitForStatement(ForStatement node) {
    var body = node.body;
    if (body is Block) {
      _computer._addRegion(
        body.leftBracket.offset,
        body.rightBracket.end,
        FoldingKind.BLOCK,
      );
    }
    super.visitForStatement(node);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    _computer._addRegion(node.name.end, node.end, FoldingKind.FUNCTION_BODY);
    super.visitFunctionDeclaration(node);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    var body = node.body;
    if (body is BlockFunctionBody) {
      _computer._addRegion(
        body.block.leftBracket.offset,
        body.block.rightBracket.end,
        FoldingKind.BLOCK,
      );
    }
    super.visitFunctionExpression(node);
  }

  @override
  void visitIfStatement(IfStatement node) {
    var thenStatement = node.thenStatement;
    if (thenStatement is Block) {
      _computer.addRegionForConditionalBlock(thenStatement);
    }
    var elseStatement = node.elseStatement;
    if (elseStatement is Block) {
      _computer.addRegionForConditionalBlock(elseStatement);
    }
    super.visitIfStatement(node);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    _computer._recordDirective(_Directive(node, node.importKeyword));
    super.visitImportDirective(node);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    _computer._recordDirective(_Directive(node, node.libraryKeyword));
    super.visitLibraryDirective(node);
  }

  @override
  void visitListLiteral(ListLiteral node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.offset,
      FoldingKind.LITERAL,
    );
    super.visitListLiteral(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    _computer._addRegion(node.name.end, node.end, FoldingKind.FUNCTION_BODY);
    super.visitMethodDeclaration(node);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    _computer._addRegionForAnnotations(node.metadata);
    super.visitMixinDeclaration(node);
  }

  @override
  void visitPartDirective(PartDirective node) {
    _computer._recordDirective(_Directive(node, node.partKeyword));
    super.visitPartDirective(node);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    _computer._recordDirective(_Directive(node, node.partKeyword));
    super.visitPartOfDirective(node);
  }

  @override
  void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
    _computer._addRegionForAnnotations(node.metadata);
    _computer._addRegion(
      node.thisKeyword.end,
      node.end,
      FoldingKind.FUNCTION_BODY,
    );

    super.visitPrimaryConstructorBody(node);
  }

  @override
  void visitRecordLiteral(RecordLiteral node) {
    _computer._addRegion(
      node.leftParenthesis.end,
      node.rightParenthesis.offset,
      FoldingKind.LITERAL,
    );
    super.visitRecordLiteral(node);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.offset,
      FoldingKind.LITERAL,
    );
    super.visitSetOrMapLiteral(node);
  }

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    _computer._addRegion(node.offset, node.end, FoldingKind.LITERAL);
    super.visitSimpleStringLiteral(node);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    _computer._addRegion(node.offset, node.end, FoldingKind.LITERAL);
    super.visitStringInterpolation(node);
  }

  @override
  void visitSwitchCase(SwitchCase node) {
    _computer._addRegion(node.colon.end, node.end, FoldingKind.BLOCK);
    super.visitSwitchCase(node);
  }

  @override
  void visitSwitchDefault(SwitchDefault node) {
    _computer._addRegion(node.colon.end, node.end, FoldingKind.BLOCK);
    super.visitSwitchDefault(node);
  }

  @override
  void visitSwitchExpression(SwitchExpression node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.end,
      FoldingKind.BLOCK,
    );
    super.visitSwitchExpression(node);
  }

  @override
  void visitSwitchExpressionCase(SwitchExpressionCase node) {
    _computer._addRegion(node.arrow.end, node.end, FoldingKind.BLOCK);
    super.visitSwitchExpressionCase(node);
  }

  @override
  void visitSwitchPatternCase(SwitchPatternCase node) {
    _computer._addRegion(node.colon.end, node.end, FoldingKind.BLOCK);
    super.visitSwitchPatternCase(node);
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    _computer._addRegion(
      node.leftBracket.end,
      node.rightBracket.end,
      FoldingKind.BLOCK,
    );
    super.visitSwitchStatement(node);
  }

  @override
  void visitTryStatement(TryStatement node) {
    _computer.addRegionForConditionalBlock(node.body);
    for (var catchNode in node.catchClauses) {
      _computer.addRegionForConditionalBlock(catchNode.body);
    }
    if (node.finallyBlock case var finallyNode?) {
      _computer.addRegionForConditionalBlock(finallyNode);
    }

    super.visitTryStatement(node);
  }

  @override
  void visitWhileStatement(WhileStatement node) {
    var body = node.body;
    if (body is Block) {
      _computer.addRegionForConditionalBlock(body);
    }
    super.visitWhileStatement(node);
  }
}

class _Directive {
  final Directive directive;
  final Token keyword;

  new(this.directive, this.keyword);
}

extension _CommentTokenExtensions on Token {
  static final _newlinePattern = RegExp(r'[\r\n]');

  /// Return the offset of the first eol character or `null` if no newlines were
  /// found.
  int? get eolOffset {
    var offset = lexeme.indexOf(_newlinePattern);
    return offset != -1 ? offset : null;
  }

  /// Return `true` if this comment is a triple-slash single line comment.
  bool get isTripleSlash => lexeme.startsWith('///');
}
