// Copyright (c) 2014, 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:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/convert_getter_to_method.dart';
import 'package:analysis_server/src/services/refactoring/convert_method_to_getter.dart';
import 'package:analysis_server/src/services/refactoring/extract_local.dart';
import 'package:analysis_server/src/services/refactoring/extract_method.dart';
import 'package:analysis_server/src/services/refactoring/extract_widget.dart';
import 'package:analysis_server/src/services/refactoring/inline_local.dart';
import 'package:analysis_server/src/services/refactoring/inline_method.dart';
import 'package:analysis_server/src/services/refactoring/move_file.dart';
import 'package:analysis_server/src/services/refactoring/rename_class_member.dart';
import 'package:analysis_server/src/services/refactoring/rename_constructor.dart';
import 'package:analysis_server/src/services/refactoring/rename_extension_member.dart';
import 'package:analysis_server/src/services/refactoring/rename_import.dart';
import 'package:analysis_server/src/services/refactoring/rename_label.dart';
import 'package:analysis_server/src/services/refactoring/rename_library.dart';
import 'package:analysis_server/src/services/refactoring/rename_local.dart';
import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/index.dart';
import 'package:analyzer/src/utilities/cancellation.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    show RefactoringMethodParameter, SourceChange;

/// [Refactoring] to convert getters into normal [MethodDeclaration]s.
abstract class ConvertGetterToMethodRefactoring implements Refactoring {
  /// Returns a new [ConvertMethodToGetterRefactoring] instance for converting
  /// [element] and all the corresponding hierarchy elements.
  factory ConvertGetterToMethodRefactoring(SearchEngine searchEngine,
      AnalysisSession session, PropertyAccessorElement element) {
    return ConvertGetterToMethodRefactoringImpl(searchEngine, session, element);
  }

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to convert normal [MethodDeclaration]s into getters.
abstract class ConvertMethodToGetterRefactoring implements Refactoring {
  /// Returns a new [ConvertMethodToGetterRefactoring] instance for converting
  /// [element] and all the corresponding hierarchy elements.
  factory ConvertMethodToGetterRefactoring(SearchEngine searchEngine,
      AnalysisSession session, ExecutableElement element) {
    return ConvertMethodToGetterRefactoringImpl(searchEngine, session, element);
  }

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to extract an expression into a local variable declaration.
abstract class ExtractLocalRefactoring implements Refactoring {
  /// Returns a new [ExtractLocalRefactoring] instance.
  factory ExtractLocalRefactoring(ResolvedUnitResult resolveResult,
      int selectionOffset, int selectionLength) = ExtractLocalRefactoringImpl;

  /// The lengths of the expressions that cover the specified selection,
  /// from the down most to the up most.
  List<int> get coveringExpressionLengths;

  /// The offsets of the expressions that cover the specified selection,
  /// from the down most to the up most.
  List<int> get coveringExpressionOffsets;

  /// True if all occurrences of the expression within the scope in which the
  /// variable will be defined should be replaced by a reference to the local
  /// variable. The expression used to initiate the refactoring will always be
  /// replaced.
  set extractAll(bool extractAll);

  /// The lengths of the expressions that would be replaced by a reference to
  /// the variable. The lengths correspond to the offsets. In other words, for a
  /// given expression, if the offset of that expression is offsets[i], then the
  /// length of that expression is lengths[i].
  List<int> get lengths;

  /// The name that the local variable should be given.
  set name(String name);

  /// The proposed names for the local variable.
  ///
  /// The first proposal should be used as the "best guess" (if it exists).
  List<String> get names;

  /// The offsets of the expressions that would be replaced by a reference to
  /// the variable.
  List<int> get offsets;

  /// Validates that the [name] is a valid identifier and is appropriate for
  /// local variable.
  ///
  /// It does not perform all the checks (such as checking for conflicts with
  /// any existing names in any of the scopes containing the current name), as
  /// many of these checks require search engine. Use [checkFinalConditions] for
  /// this level of checking.
  RefactoringStatus checkName();

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to extract an [Expression] or [Statement]s into a new method.
abstract class ExtractMethodRefactoring implements Refactoring {
  /// Returns a new [ExtractMethodRefactoring] instance.
  factory ExtractMethodRefactoring(
      SearchEngine searchEngine,
      ResolvedUnitResult resolveResult,
      int selectionOffset,
      int selectionLength) {
    return ExtractMethodRefactoringImpl(
        searchEngine, resolveResult, selectionOffset, selectionLength);
  }

  /// True if a getter could be created rather than a method.
  bool get canCreateGetter;

  /// True if a getter should be created rather than a method.
  set createGetter(bool createGetter);

  /// True if all occurrences of the expression or statements should be replaced
  /// by an invocation of the method. The expression or statements used to
  /// initiate the refactoring will always be replaced.
  set extractAll(bool extractAll);

  /// The lengths of the expressions or statements that would be replaced by an
  /// invocation of the method. The lengths correspond to the offsets.
  /// In other words, for a given expression (or block of statements), if the
  /// offset of that expression is offsets[i], then the length of that
  /// expression is lengths[i].
  List<int> get lengths;

  /// The name that the method should be given.
  set name(String name);

  /// The proposed names for the method.
  ///
  /// The first proposal should be used as the "best guess" (if it exists).
  List<String> get names;

  /// The offsets of the expressions or statements that would be replaced by an
  /// invocation of the method.
  List<int> get offsets;

  /// The proposed parameters for the method.
  List<RefactoringMethodParameter> get parameters;

  /// The parameters that should be defined for the method.
  set parameters(List<RefactoringMethodParameter> parameters);

  /// The proposed return type for the method.
  String get returnType;

  /// The return type that should be defined for the method.
  set returnType(String returnType);

  /// Validates that the [name] is a valid identifier and is appropriate for a
  /// method.
  ///
  /// It does not perform all the checks (such as checking for conflicts with
  /// any existing names in any of the scopes containing the current name), as
  /// many of these checks require search engine. Use [checkFinalConditions] for
  /// this level of checking.
  RefactoringStatus checkName();

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to extract a widget creation expression or a method returning
/// a widget, into a new stateless or stateful widget.
abstract class ExtractWidgetRefactoring implements Refactoring {
  /// Returns a new [ExtractWidgetRefactoring] instance.
  factory ExtractWidgetRefactoring(SearchEngine searchEngine,
      ResolvedUnitResult resolveResult, int offset, int length) {
    return ExtractWidgetRefactoringImpl(
        searchEngine, resolveResult, offset, length);
  }

  /// The name that the class should be given.
  set name(String name);

  /// Validates that the [name] is a valid identifier and is appropriate for a
  /// class.
  ///
  /// It does not perform all the checks (such as checking for conflicts with
  /// any existing names in any of the scopes containing the current name), as
  /// many of these checks require search engine. Use [checkFinalConditions] for
  /// this level of checking.
  RefactoringStatus checkName();

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to inline a local [VariableElement].
abstract class InlineLocalRefactoring implements Refactoring {
  /// Returns a new [InlineLocalRefactoring] instance.
  factory InlineLocalRefactoring(
      SearchEngine searchEngine, ResolvedUnitResult resolveResult, int offset) {
    return InlineLocalRefactoringImpl(searchEngine, resolveResult, offset);
  }

  /// Returns the number of references to the [VariableElement].
  int get referenceCount;

  /// Returns the name of the variable being inlined.
  String? get variableName;

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to inline an [ExecutableElement].
abstract class InlineMethodRefactoring implements Refactoring {
  /// Returns a new [InlineMethodRefactoring] instance.
  factory InlineMethodRefactoring(
      SearchEngine searchEngine, ResolvedUnitResult resolveResult, int offset) {
    return InlineMethodRefactoringImpl(searchEngine, resolveResult, offset);
  }

  /// The name of the class enclosing the method being inlined.
  /// If not a class member is being inlined, then `null`.
  String? get className;

  /// True if the method being inlined should be removed.
  /// It is an error if this field is `true` and [inlineAll] is `false`.
  set deleteSource(bool deleteSource);

  /// True if all invocations of the method should be inlined, or false if only
  /// the invocation site used to create this refactoring should be inlined.
  set inlineAll(bool inlineAll);

  /// True if the declaration of the method is selected.
  /// So, all references should be inlined.
  bool get isDeclaration;

  /// The name of the method (or function) being inlined.
  String? get methodName;

  /// Return `true` if refactoring is available, possibly without checking all
  /// initial conditions.
  ///
  /// This value may be used to control the visibility of the refactor in the UI
  /// so that it doesn't show up in locations that are obviously not
  /// appropriate. Initial conditions may perform additional checks (and provide
  /// user-friendly messages) for locations where a user might reasonably expect
  /// to see the refactor but it's not valid for a less obvious reason.
  bool isAvailable();
}

/// [Refactoring] to move/rename a file or folder.
abstract class MoveFileRefactoring implements Refactoring {
  /// Returns a new [MoveFileRefactoring] instance.
  factory MoveFileRefactoring(ResourceProvider resourceProvider,
      RefactoringWorkspace workspace, String oldFilePath) {
    return MoveFileRefactoringImpl(resourceProvider, workspace, oldFilePath);
  }

  /// The new file path to which the given file is being moved.
  set newFile(String newName);
}

/// Abstract interface for all refactorings.
abstract class Refactoring {
  set cancellationToken(CancellationToken token);

  /// The ids of source edits that are not known to be valid.
  ///
  /// An edit is not known to be valid if there was insufficient type
  /// information for the server to be able to determine whether or not the code
  /// needs to be modified, such as when a member is being renamed and there is
  /// a reference to a member from an unknown type. This field will be omitted
  /// if the change field is omitted or if there are no potential edits for the
  /// refactoring.
  List<String> get potentialEditIds;

  /// Returns the human readable name of this [Refactoring].
  String get refactoringName;

  /// Checks all conditions - [checkInitialConditions] and
  /// [checkFinalConditions] to decide if refactoring can be performed.
  Future<RefactoringStatus> checkAllConditions();

  /// Validates environment to check if this refactoring can be performed.
  ///
  /// This check may be slow, because many refactorings use search engine.
  Future<RefactoringStatus> checkFinalConditions();

  /// Validates arguments to check if this refactoring can be performed.
  ///
  /// This check should be quick because it is used often as arguments change.
  Future<RefactoringStatus> checkInitialConditions();

  /// Returns the [Change] to apply to perform this refactoring.
  Future<SourceChange> createChange();
}

/// Information about the workspace refactorings operate it.
class RefactoringWorkspace {
  final Iterable<AnalysisDriver> drivers;
  final SearchEngine searchEngine;

  RefactoringWorkspace(this.drivers, this.searchEngine);

  /// Whether the [element] is defined in a file that is in a context root.
  bool containsElement(Element element) {
    return containsFile(element.source!.fullName);
  }

  /// Whether the file with the given [path] is in a context root.
  bool containsFile(String path) {
    return drivers.any((driver) {
      return driver.analysisContext!.contextRoot.isAnalyzed(path);
    });
  }

  /// Returns the drivers that have [path] in a context root.
  Iterable<AnalysisDriver> driversContaining(String path) {
    return drivers.where((driver) {
      return driver.analysisContext!.contextRoot.isAnalyzed(path);
    });
  }
}

/// Abstract [Refactoring] for renaming some [Element].
abstract class RenameRefactoring implements Refactoring {
  /// Returns the human-readable description of the kind of element being
  /// renamed (such as “class” or “function type alias”).
  String get elementKindName;

  /// Sets the new name for the [Element].
  set newName(String newName);

  /// Returns the old name of the [Element] being renamed.
  String get oldName;

  /// Validates that the [newName] is a valid identifier and is appropriate for
  /// the type of the [Element] being renamed.
  ///
  /// It does not perform all the checks (such as checking for conflicts with
  /// any existing names in any of the scopes containing the current name), as
  /// many of these checks require search engine. Use [checkFinalConditions] for
  /// this level of checking.
  RefactoringStatus checkNewName();

  /// Returns a new [RenameRefactoring] instance for renaming [element],
  /// maybe `null` if there is no support for renaming [Element]s of the given
  /// type.
  static RenameRefactoring? create(RefactoringWorkspace workspace,
      ResolvedUnitResult resolvedUnit, Element? element) {
    var session = resolvedUnit.session;
    if (element == null) {
      return null;
    }
    if (element is PropertyAccessorElement) {
      element = element.variable;
    }
    var enclosingElement = element.enclosingElement;
    if (enclosingElement is CompilationUnitElement) {
      return RenameUnitMemberRefactoringImpl(workspace, resolvedUnit, element);
    }
    if (element is ConstructorElement) {
      return RenameConstructorRefactoringImpl(workspace, session, element);
    }
    if (element is ImportElement2) {
      return RenameImportRefactoringImpl(workspace, session, element);
    }
    if (element is LabelElement) {
      return RenameLabelRefactoringImpl(workspace, element);
    }
    if (element is LibraryElement) {
      return RenameLibraryRefactoringImpl(workspace, element);
    }
    if (element is LocalElement) {
      return RenameLocalRefactoringImpl(workspace, session, element);
    }
    if (enclosingElement is ClassElement) {
      return RenameClassMemberRefactoringImpl(
          workspace, session, enclosingElement, element);
    }
    if (enclosingElement is ExtensionElement) {
      return RenameExtensionMemberRefactoringImpl(
          workspace, session, enclosingElement, element);
    }
    return null;
  }

  /// Given a node/element, finds the best element to rename (for example
  /// the class when on the `new` keyword).
  static RenameRefactoringElement? getElementToRename(
      AstNode node, Element? element) {
    var offset = node.offset;
    var length = node.length;

    if (node is SimpleIdentifier && element is ParameterElement) {
      element = declaredParameterElement(node, element);
    }

    if (element is FieldFormalParameterElement) {
      element = element.field;
    }

    // Use the prefix offset/length when renaming an import directive.
    if (node is ImportDirective && element is ImportElement2) {
      var prefix = node.prefix;
      if (prefix != null) {
        offset = prefix.offset;
        length = prefix.length;
      } else {
        // -1 means the name does not exist yet.
        offset = -1;
        length = 0;
      }
    }

    // Rename the class when on `new` in an instance creation.
    if (node is InstanceCreationExpression) {
      var creation = node;
      var typeIdentifier = creation.constructorName.type.name;
      element = typeIdentifier.staticElement;
      offset = typeIdentifier.offset;
      length = typeIdentifier.length;
    }

    if (element == null) {
      return null;
    }

    return RenameRefactoringElement(element, offset, length);
  }
}

class RenameRefactoringElement {
  final Element element;
  final int offset;
  final int length;

  RenameRefactoringElement(this.element, this.offset, this.length);
}
