// Copyright (c) 2022, 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/source_range.dart';

/// A selection within a compilation unit.
class Selection {
  /// The offset of the selection.
  final int offset;

  /// The length of the selection.
  final int length;

  /// The most deeply nested node whose range completely includes the selected
  /// range of characters.
  final AstNode coveringNode;

  /// Initialize a newly created selection to include the characters starting at
  /// the [offset] and including [length] characters, all of which fall within
  /// the [coveringNode].
  Selection({
    required this.offset,
    required this.length,
    required this.coveringNode,
  });

  bool isCoveredByNode(AstNode node) {
    return node.offset <= offset && offset + length <= node.end;
  }

  bool isCoveredByToken(Token token) {
    return token.offset <= offset && offset + length <= token.end;
  }

  /// Returns the contiguous subset of [coveringNode] children that are at
  /// least partially covered by the selection. Touching is not enough.
  ///
  /// A list of nodes is defined to be _contiguous_ if they are syntactically
  /// adjacent with no intervening tokens other than comments or commas. For
  /// example, the nodes might be a sequence of members in a compilation unit, a
  /// sequence of statements in a block, or a sequence of parameters in a
  /// parameter list that don't cross a separator such as `{` or `[`.
  List<AstNode> nodesInRange() {
    var rangeFinder = _ChildrenFinder(SourceRange(offset, length));
    coveringNode.accept(rangeFinder);
    return rangeFinder.nodes;
  }
}

/// A visitor used to find a sequence of nodes within the node being visited
/// that together cover the range.
class _ChildrenFinder extends SimpleAstVisitor<void> {
  /// The range that the sequence of nodes must cover.
  final SourceRange range;

  /// The nodes within the range.
  List<AstNode> nodes = [];

  /// Initialize a newly created visitor.
  _ChildrenFinder(this.range);

  @override
  void visitAdjacentStrings(AdjacentStrings node) {
    _fromList(node.strings);
  }

  @override
  void visitArgumentList(ArgumentList node) {
    _fromList(node.arguments);
  }

  @override
  void visitBlock(Block node) {
    _fromList(node.statements);
  }

  @override
  void visitCascadeExpression(CascadeExpression node) {
    _fromList(node.cascadeSections);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    _fromList(node.metadata) || _fromList(node.members);
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    _fromList(node.metadata);
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    // TODO(brianwilkerson): Support selecting both directives and declarations.
    _fromList(node.directives) || _fromList(node.declarations);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    _fromList(node.metadata) || _fromList(node.initializers);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    _fromList(node.metadata);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitDottedName(DottedName node) {
    _fromList(node.components);
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    _fromList(node.metadata) ||
        _fromList(node.constants) ||
        _fromList(node.members);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    _fromList(node.metadata) ||
        _fromList(node.configurations) ||
        _fromList(node.combinators);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    _fromList(node.metadata) || _fromList(node.members);
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitForEachPartsWithPattern(ForEachPartsWithPattern node) {
    _fromList(node.metadata);
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    var delimiter = node.leftDelimiter;
    if (delimiter == null || !range.contains(delimiter.offset)) {
      _fromList(node.parameters);
    }
  }

  @override
  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
    _fromList(node.updaters);
  }

  @override
  void visitForPartsWithExpression(ForPartsWithExpression node) {
    _fromList(node.updaters);
  }

  @override
  void visitForPartsWithPattern(ForPartsWithPattern node) {
    _fromList(node.updaters);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    _fromList(node.metadata);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    _fromList(node.metadata);
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    _fromList(node.hiddenNames);
  }

  @override
  void visitImplementsClause(ImplementsClause node) {
    _fromList(node.interfaces);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    _fromList(node.metadata) ||
        _fromList(node.configurations) ||
        _fromList(node.combinators);
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    _fromList(node.labels);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    _fromList(node.metadata);
  }

  @override
  void visitLibraryIdentifier(LibraryIdentifier node) {
    _fromList(node.components);
  }

  @override
  void visitListLiteral(ListLiteral node) {
    _fromList(node.elements);
  }

  @override
  void visitListPattern(ListPattern node) {
    _fromList(node.elements);
  }

  @override
  void visitMapPattern(MapPattern node) {
    _fromList(node.elements);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    _fromList(node.metadata) || _fromList(node.members);
  }

  @override
  void visitMixinOnClause(MixinOnClause node) {
    _fromList(node.superclassConstraints);
  }

  @override
  void visitObjectPattern(ObjectPattern node) {
    _fromList(node.fields);
  }

  @override
  void visitPartDirective(PartDirective node) {
    _fromList(node.metadata) || _fromList(node.configurations);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    _fromList(node.metadata);
  }

  @override
  void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitRecordLiteral(RecordLiteral node) {
    _fromList(node.fields);
  }

  @override
  void visitRecordPattern(RecordPattern node) {
    _fromList(node.fields);
  }

  @override
  void visitRecordTypeAnnotation(RecordTypeAnnotation node) {
    _fromList(node.positionalFields);
  }

  @override
  void visitRecordTypeAnnotationNamedField(
    RecordTypeAnnotationNamedField node,
  ) {
    _fromList(node.metadata);
  }

  @override
  void visitRecordTypeAnnotationNamedFields(
    RecordTypeAnnotationNamedFields node,
  ) {
    _fromList(node.fields);
  }

  @override
  void visitRecordTypeAnnotationPositionalField(
    RecordTypeAnnotationPositionalField node,
  ) {
    _fromList(node.metadata);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    _fromList(node.elements);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    _fromList(node.shownNames);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    _fromList(node.elements);
  }

  @override
  void visitSuperFormalParameter(SuperFormalParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitSwitchCase(SwitchCase node) {
    _fromList(node.labels) || _fromList(node.statements);
  }

  @override
  void visitSwitchDefault(SwitchDefault node) {
    _fromList(node.labels) || _fromList(node.statements);
  }

  @override
  void visitSwitchExpression(SwitchExpression node) {
    _fromList(node.cases);
  }

  @override
  void visitSwitchPatternCase(SwitchPatternCase node) {
    _fromList(node.labels) || _fromList(node.statements);
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    _fromList(node.members);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    _fromList(node.metadata);
  }

  @override
  void visitTryStatement(TryStatement node) {
    _fromList(node.catchClauses);
  }

  @override
  void visitTypeArgumentList(TypeArgumentList node) {
    _fromList(node.arguments);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    _fromList(node.metadata);
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    _fromList(node.typeParameters);
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    _fromList(node.metadata) || _fromList(node.variables);
  }

  @override
  void visitWithClause(WithClause node) {
    _fromList(node.mixinTypes);
  }

  /// If one or more of the [elements] in the list can cover the [range], then
  /// add the elements to the list of [nodes] and return `true`.
  bool _fromList(List<AstNode> elements) {
    var first = elements.length;
    for (; first > 0; first--) {
      var element = elements[first - 1];
      if (element.end <= range.offset) {
        break;
      }
    }

    var last = first;
    for (; last < elements.length; last++) {
      var element = elements[last];
      if (element.offset >= range.end) {
        break;
      }
      nodes.add(element);
    }

    return nodes.isNotEmpty;
  }
}

extension CompilationUnitExtension on CompilationUnit {
  /// Return the selection that includes the characters starting at the [offset]
  /// with the given [length].
  Selection? select({required int offset, required int length}) {
    var coveringNode = nodeCovering(offset: offset, length: length);
    if (coveringNode == null) {
      return null;
    }
    return Selection(
      offset: offset,
      length: length,
      coveringNode: coveringNode,
    );
  }
}
