// 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 'dart:collection';

import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/utilities/strings.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

const String _TOKEN_SEPARATOR = '\uFFFF';

/// [ExtractLocalRefactoring] implementation.
class ExtractLocalRefactoringImpl extends RefactoringImpl
    implements ExtractLocalRefactoring {
  final ResolvedUnitResult resolveResult;
  final int selectionOffset;
  final int selectionLength;
  late SourceRange selectionRange;
  late CorrectionUtils utils;

  late String name;
  bool extractAll = true;
  @override
  final List<int> coveringExpressionOffsets = <int>[];
  @override
  final List<int> coveringExpressionLengths = <int>[];
  @override
  final List<String> names = <String>[];
  @override
  final List<int> offsets = <int>[];
  @override
  final List<int> lengths = <int>[];

  FunctionBody? coveringFunctionBody;
  Expression? singleExpression;
  String? stringLiteralPart;
  final List<SourceRange> occurrences = <SourceRange>[];
  final Map<Element, int> elementIds = <Element, int>{};
  Set<String> excludedVariableNames = <String>{};

  ExtractLocalRefactoringImpl(
      this.resolveResult, this.selectionOffset, this.selectionLength) {
    selectionRange = SourceRange(selectionOffset, selectionLength);
    utils = CorrectionUtils(resolveResult);
  }

  String get file => resolveResult.path;

  @override
  String get refactoringName => 'Extract Local Variable';

  CompilationUnit get unit => resolveResult.unit;

  CompilationUnitElement get unitElement => unit.declaredElement!;

  String get _declarationKeyword {
    if (_isPartOfConstantExpression(singleExpression)) {
      return 'const';
    } else if (_isLintEnabled(LintNames.prefer_final_locals)) {
      return 'final';
    } else {
      return 'var';
    }
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() {
    var result = RefactoringStatus();
    result.addStatus(checkName());
    return Future.value(result);
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() {
    var result = RefactoringStatus();
    // selection
    result.addStatus(_checkSelection());
    if (result.hasFatalError) {
      return Future.value(result);
    }
    // occurrences
    _prepareOccurrences();
    _prepareOffsetsLengths();
    // names
    excludedVariableNames =
        utils.findPossibleLocalVariableConflicts(selectionOffset);
    _prepareNames();
    // done
    return Future.value(result);
  }

  @override
  RefactoringStatus checkName() {
    var result = RefactoringStatus();
    result.addStatus(validateVariableName(name));
    if (excludedVariableNames.contains(name)) {
      result.addError(
          format("The name '{0}' is already used in the scope.", name));
    }
    return result;
  }

  @override
  Future<SourceChange> createChange() {
    var change = SourceChange(refactoringName);
    // prepare occurrences
    late final List<SourceRange> occurrences;
    if (extractAll) {
      occurrences = this.occurrences;
    } else {
      occurrences = [selectionRange];
    }
    occurrences.sort((a, b) => a.offset - b.offset);
    // If the whole expression of a statement is selected, like '1 + 2',
    // then convert it into a variable declaration statement.
    final singleExpression = this.singleExpression;
    if (singleExpression != null &&
        singleExpression.parent is ExpressionStatement &&
        occurrences.length == 1) {
      var keyword = _declarationKeyword;
      var declarationSource = '$keyword $name = ';
      var edit = SourceEdit(singleExpression.offset, 0, declarationSource);
      doSourceChange_addElementEdit(change, unitElement, edit);
      return Future.value(change);
    }
    // prepare positions
    var positions = <Position>[];
    var occurrencesShift = 0;
    void addPosition(int offset) {
      positions.add(Position(file, offset));
    }

    // add variable declaration
    {
      String declarationCode;
      int nameOffsetInDeclarationCode;
      if (stringLiteralPart != null) {
        declarationCode = 'var ';
        nameOffsetInDeclarationCode = declarationCode.length;
        declarationCode += "$name = '$stringLiteralPart';";
      } else {
        var keyword = _declarationKeyword;
        var initializerCode = utils.getRangeText(selectionRange);
        declarationCode = '$keyword ';
        nameOffsetInDeclarationCode = declarationCode.length;
        declarationCode += '$name = $initializerCode;';
      }
      // prepare location for declaration
      var target = _findDeclarationTarget(occurrences);
      var eol = utils.endOfLine;
      // insert variable declaration
      if (target is Statement) {
        var prefix = utils.getNodePrefix(target);
        var edit = SourceEdit(target.offset, 0, declarationCode + eol + prefix);
        doSourceChange_addElementEdit(change, unitElement, edit);
        addPosition(edit.offset + nameOffsetInDeclarationCode);
        occurrencesShift = edit.replacement.length;
      } else if (target is ExpressionFunctionBody) {
        var prefix = utils.getNodePrefix(target.parent!);
        var indent = utils.getIndent(1);
        var expr = target.expression;
        {
          var code = '{' + eol + prefix + indent;
          addPosition(
              target.offset + code.length + nameOffsetInDeclarationCode);
          code += declarationCode + eol;
          code += prefix + indent + 'return ';
          var edit =
              SourceEdit(target.offset, expr.offset - target.offset, code);
          occurrencesShift = target.offset + code.length - expr.offset;
          doSourceChange_addElementEdit(change, unitElement, edit);
        }
        doSourceChange_addElementEdit(
            change,
            unitElement,
            SourceEdit(
                expr.end, target.end - expr.end, ';' + eol + prefix + '}'));
      }
    }
    // prepare replacement
    var occurrenceReplacement = name;
    if (stringLiteralPart != null) {
      occurrenceReplacement = '\${$name}';
      occurrencesShift += 2;
    }
    // replace occurrences with variable reference
    for (var range in occurrences) {
      var edit = newSourceEdit_range(range, occurrenceReplacement);
      addPosition(range.offset + occurrencesShift);
      occurrencesShift += name.length - range.length;
      doSourceChange_addElementEdit(change, unitElement, edit);
    }
    // add the linked group
    change.addLinkedEditGroup(LinkedEditGroup(
        positions,
        name.length,
        names
            .map((name) =>
                LinkedEditSuggestion(name, LinkedEditSuggestionKind.VARIABLE))
            .toList()));
    // done
    return Future.value(change);
  }

  @override
  bool isAvailable() {
    return !_checkSelection().hasFatalError;
  }

  /// Checks if [selectionRange] selects [Expression] which can be extracted,
  /// and location of this [Expression] in AST allows extracting.
  RefactoringStatus _checkSelection() {
    if (selectionOffset <= 0) {
      return RefactoringStatus.fatal(
          'The selection offset must be greater than zero.');
    }
    if (selectionOffset + selectionLength >= resolveResult.content.length) {
      return RefactoringStatus.fatal(
          'The selection end offset must be less then the length of the file.');
    }

    var selectionStr = utils.getRangeText(selectionRange);

    // exclude whitespaces
    {
      var numLeading = countLeadingWhitespaces(selectionStr);
      var numTrailing = countTrailingWhitespaces(selectionStr);
      var offset = selectionRange.offset + numLeading;
      var end = selectionRange.end - numTrailing;
      selectionRange = SourceRange(offset, end - offset);
    }

    // get covering node
    var coveringNode = NodeLocator(selectionRange.offset, selectionRange.end)
        .searchWithin(unit);

    // We need an enclosing function.
    // If it has a block body, we can add a new variable declaration statement
    // into this block.  If it has an expression body, we can convert it into
    // the block body first.
    coveringFunctionBody = coveringNode?.thisOrAncestorOfType<FunctionBody>();
    if (coveringFunctionBody == null) {
      return RefactoringStatus.fatal(
          'An expression inside a function must be selected '
          'to activate this refactoring.');
    }

    // part of string literal
    if (coveringNode is StringLiteral) {
      if (selectionRange.length != 0 &&
          selectionRange.offset > coveringNode.offset &&
          selectionRange.end < coveringNode.end) {
        stringLiteralPart = selectionStr;
        return RefactoringStatus();
      }
    }
    // compute covering expressions
    for (var node = coveringNode; node != null; node = node.parent) {
      var parent = node.parent;
      // skip some nodes
      if (node is ArgumentList ||
          node is AssignmentExpression ||
          node is NamedExpression ||
          node is TypeArgumentList) {
        continue;
      }
      if (node is ConstructorName || node is Label || node is TypeName) {
        singleExpression = null;
        coveringExpressionOffsets.clear();
        coveringExpressionLengths.clear();
        continue;
      }
      // cannot extract the name part of a property access
      if (parent is PrefixedIdentifier && parent.identifier == node ||
          parent is PropertyAccess && parent.propertyName == node) {
        continue;
      }
      // stop if not an Expression
      if (node is! Expression) {
        break;
      }
      // stop at void method invocations
      if (node is MethodInvocation) {
        var invocation = node;
        var element = invocation.methodName.staticElement;
        if (element is ExecutableElement && element.returnType.isVoid) {
          if (singleExpression == null) {
            return RefactoringStatus.fatal(
                'Cannot extract the void expression.',
                newLocation_fromNode(node));
          }
          break;
        }
      }
      // fatal selection problems
      if (coveringExpressionOffsets.isEmpty) {
        if (node is SimpleIdentifier) {
          if (node.inDeclarationContext()) {
            return RefactoringStatus.fatal(
                'Cannot extract the name part of a declaration.',
                newLocation_fromNode(node));
          }
          var element = node.staticElement;
          if (element is FunctionElement || element is MethodElement) {
            continue;
          }
        }
        if (parent is AssignmentExpression && parent.leftHandSide == node) {
          return RefactoringStatus.fatal(
              'Cannot extract the left-hand side of an assignment.',
              newLocation_fromNode(node));
        }
      }
      // set selected expression
      singleExpression ??= node;
      // add the expression range
      coveringExpressionOffsets.add(node.offset);
      coveringExpressionLengths.add(node.length);
    }
    // single node selected
    if (singleExpression != null) {
      selectionRange = range.node(singleExpression!);
      return RefactoringStatus();
    }
    // invalid selection
    return RefactoringStatus.fatal(
        'Expression must be selected to activate this refactoring.');
  }

  /// Return an unique identifier for the given [Element], or `null` if
  /// [element] is `null`.
  int? _encodeElement(Element? element) {
    if (element == null) {
      return null;
    }
    var id = elementIds[element];
    if (id == null) {
      id = elementIds.length;
      elementIds[element] = id;
    }
    return id;
  }

  /// Returns an [Element]-sensitive encoding of [tokens].
  /// Each [Token] with a [LocalVariableElement] has a suffix of the element id.
  ///
  /// So, we can distinguish different local variables with the same name, if
  /// there are multiple variables with the same name are declared in the
  /// function we are searching occurrences in.
  String _encodeExpressionTokens(Expression expr, List<Token> tokens) {
    // prepare Token -> LocalElement map
    Map<Token, Element> map = HashMap<Token, Element>(
        equals: (Token a, Token b) => a.lexeme == b.lexeme,
        hashCode: (Token t) => t.lexeme.hashCode);
    expr.accept(_TokenLocalElementVisitor(map));
    // map and join tokens
    var result = tokens.map((Token token) {
      var tokenString = token.lexeme;
      // append token's Element id
      var element = map[token];
      if (element != null) {
        var elementId = _encodeElement(element);
        if (elementId != null) {
          tokenString += '-$elementId';
        }
      }
      // done
      return tokenString;
    }).join(_TOKEN_SEPARATOR);
    return result + _TOKEN_SEPARATOR;
  }

  /// Return the [AstNode] to defined the variable before.
  /// It should be accessible by all the given [occurrences].
  AstNode? _findDeclarationTarget(List<SourceRange> occurrences) {
    var nodes = _findNodes(occurrences);
    var commonParent = getNearestCommonAncestor(nodes);
    // Block
    if (commonParent is Block) {
      var firstParents = getParents(nodes[0]);
      var commonIndex = firstParents.indexOf(commonParent);
      return firstParents[commonIndex + 1];
    }
    // ExpressionFunctionBody
    var expressionBody = _getEnclosingExpressionBody(commonParent);
    if (expressionBody != null) {
      return expressionBody;
    }
    // single Statement
    AstNode? target = commonParent?.thisOrAncestorOfType<Statement>();
    while (target != null) {
      var parent = target.parent;
      if (parent is Block) {
        break;
      }
      target = parent;
    }
    return target;
  }

  /// Returns [AstNode]s at the offsets of the given [SourceRange]s.
  List<AstNode> _findNodes(List<SourceRange> ranges) {
    var nodes = <AstNode>[];
    for (var range in ranges) {
      var node = NodeLocator(range.offset).searchWithin(unit)!;
      nodes.add(node);
    }
    return nodes;
  }

  /// Returns the [ExpressionFunctionBody] that encloses [node], or `null`
  /// if [node] is not enclosed with an [ExpressionFunctionBody].
  ExpressionFunctionBody? _getEnclosingExpressionBody(AstNode? node) {
    while (node != null) {
      if (node is Statement) {
        return null;
      }
      if (node is ExpressionFunctionBody) {
        return node;
      }
      node = node.parent;
    }
    return null;
  }

  bool _isLintEnabled(String name) {
    var analysisOptions = unitElement.context.analysisOptions;
    return analysisOptions.isLintEnabled(name);
  }

  bool _isPartOfConstantExpression(AstNode? node) {
    if (node == null) {
      return false;
    }
    if (node is TypedLiteral) {
      return node.isConst;
    }
    if (node is InstanceCreationExpression) {
      return node.isConst;
    }
    if (node is ArgumentList ||
        node is ConditionalExpression ||
        node is BinaryExpression ||
        node is ParenthesizedExpression ||
        node is PrefixExpression ||
        node is Literal ||
        node is MapLiteralEntry) {
      return _isPartOfConstantExpression(node.parent);
    }
    return false;
  }

  void _prepareNames() {
    names.clear();
    final stringLiteralPart = this.stringLiteralPart;
    final singleExpression = this.singleExpression;
    if (stringLiteralPart != null) {
      names.addAll(getVariableNameSuggestionsForText(
          stringLiteralPart, excludedVariableNames));
    } else if (singleExpression != null) {
      names.addAll(getVariableNameSuggestionsForExpression(
          singleExpression.staticType,
          singleExpression,
          excludedVariableNames));
    }
  }

  /// Prepares all occurrences of the source which matches given selection,
  /// sorted by offsets.
  void _prepareOccurrences() {
    occurrences.clear();
    elementIds.clear();

    // prepare selection
    String? selectionSource;
    final singleExpression = this.singleExpression;
    if (singleExpression != null) {
      var tokens = TokenUtils.getNodeTokens(singleExpression);
      selectionSource = _encodeExpressionTokens(singleExpression, tokens);
    }
    // visit function
    coveringFunctionBody!.accept(_OccurrencesVisitor(
        this, occurrences, selectionSource, unit.featureSet));
  }

  void _prepareOffsetsLengths() {
    offsets.clear();
    lengths.clear();
    for (var occurrence in occurrences) {
      offsets.add(occurrence.offset);
      lengths.add(occurrence.length);
    }
  }
}

class _OccurrencesVisitor extends GeneralizingAstVisitor<void> {
  final ExtractLocalRefactoringImpl ref;
  final List<SourceRange> occurrences;
  final String? selectionSource;
  final FeatureSet featureSet;

  _OccurrencesVisitor(
      this.ref, this.occurrences, this.selectionSource, this.featureSet);

  @override
  void visitExpression(Expression node) {
    _tryToFindOccurrence(node);
    super.visitExpression(node);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var parent = node.parent;
    if (parent is VariableDeclaration && parent.name == node ||
        parent is AssignmentExpression && parent.leftHandSide == node) {
      return;
    }
    super.visitSimpleIdentifier(node);
  }

  @override
  void visitStringLiteral(StringLiteral node) {
    var stringLiteralPart = ref.stringLiteralPart;
    if (stringLiteralPart != null) {
      var length = stringLiteralPart.length;
      var value = ref.utils.getNodeText(node);
      var lastIndex = 0;
      while (true) {
        var index = value.indexOf(stringLiteralPart, lastIndex);
        if (index == -1) {
          break;
        }
        lastIndex = index + length;
        var start = node.offset + index;
        var range = SourceRange(start, length);
        occurrences.add(range);
      }
      return;
    }
    visitExpression(node);
  }

  void _addOccurrence(SourceRange range) {
    if (range.intersects(ref.selectionRange)) {
      occurrences.add(ref.selectionRange);
    } else {
      occurrences.add(range);
    }
  }

  void _tryToFindOccurrence(Expression node) {
    var nodeTokens = TokenUtils.getNodeTokens(node);
    var nodeSource = ref._encodeExpressionTokens(node, nodeTokens);
    if (nodeSource == selectionSource) {
      _addOccurrence(range.node(node));
    }
  }
}

class _TokenLocalElementVisitor extends RecursiveAstVisitor<void> {
  final Map<Token, Element> map;

  _TokenLocalElementVisitor(this.map);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var element = node.staticElement;
    if (element is LocalVariableElement) {
      map[node.token] = element;
    }
  }
}
