// 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 NamedType) {
        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;
    }
  }
}
