// 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:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/util.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/source/source_range.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class ExtractLocalVariable extends CorrectionProducer {
  @override
  FixKind get fixKind => DartFixKind.EXTRACT_LOCAL_VARIABLE;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    final node = this.node;
    if (node is! SimpleIdentifier) {
      return;
    }

    var parent = node.parent;

    if (parent is MethodInvocation && parent.methodName == node) {
      await _rewrite(
        builder: builder,
        target: parent.target,
      );
    }

    if (parent is PrefixedIdentifier && parent.identifier == node) {
      await _rewrite(
        builder: builder,
        target: parent.prefix,
      );
    }

    if (parent is PropertyAccess && parent.propertyName == node) {
      await _rewrite(
        builder: builder,
        target: parent.target,
      );
    }
  }

  Future<void> _rewrite({
    required ChangeBuilder builder,
    required Expression? target,
  }) async {
    if (target is PrefixedIdentifier) {
      await _rewriteProperty(
        builder: builder,
        target: target,
        targetProperty: target.staticElement,
      );
    }

    if (target is PropertyAccess) {
      await _rewriteProperty(
        builder: builder,
        target: target,
        targetProperty: target.propertyName.staticElement,
      );
    }

    if (target is SimpleIdentifier) {
      await _rewriteProperty(
        builder: builder,
        target: target,
        targetProperty: target.staticElement,
      );
    }
  }

  Future<void> _rewriteProperty({
    required ChangeBuilder builder,
    required Expression target,
    required Element? targetProperty,
  }) async {
    if (targetProperty is PropertyAccessorElement &&
        targetProperty.isGetter &&
        typeSystem.isPotentiallyNullable(targetProperty.returnType)) {
      AstNode? enclosingNode = target;
      while (true) {
        if (enclosingNode == null || enclosingNode is FunctionBody) {
          return;
        }
        if (enclosingNode is IfStatement) {
          var condition = enclosingNode.condition;
          if (condition is BinaryExpression &&
              condition.rightOperand is NullLiteral &&
              condition.operator.type == TokenType.BANG_EQ) {
            var encoder = _ExpressionEncoder();
            var leftCode = encoder.encode(condition.leftOperand);
            var targetCode = encoder.encode(target);
            if (leftCode == targetCode) {
              var occurrences = <SourceRange>[];
              enclosingNode.accept(
                _OccurrencesVisitor(encoder, occurrences, leftCode),
              );

              var ifOffset = enclosingNode.offset;
              var ifLineOffset = utils.getLineContentStart(ifOffset);
              var prefix = utils.getLinePrefix(ifOffset);

              var initializerCode = utils.getNodeText(target);
              if (target is SimpleIdentifier) {
                initializerCode = 'this.$initializerCode';
              }

              await builder.addDartFileEdit(file, (builder) {
                var propertyName = targetProperty.name;
                builder.addInsertion(ifLineOffset, (builder) {
                  builder.write(prefix);
                  builder.writeln('final $propertyName = $initializerCode;');
                });
                for (var occurrence in occurrences) {
                  builder.addSimpleReplacement(occurrence, propertyName);
                }
              });
              return;
            }
          }
          break;
        }
        enclosingNode = enclosingNode.parent;
      }
    }
  }

  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
  static ExtractLocalVariable newInstance() => ExtractLocalVariable();
}

class _ExpressionEncoder {
  final Map<Element, int> _elementIds = {};

  String encode(Expression node) {
    var tokens = TokenUtils.getNodeTokens(node);

    var tokenToElementMap = Map<Token, Element>.identity();
    node.accept(
      _FunctionAstVisitor(
        simpleIdentifier: (node) {
          var element = node.staticElement;
          if (element != null) {
            tokenToElementMap[node.token] = element;
          }
        },
      ),
    );

    var tokensWithId = tokens.map((token) {
      var tokenString = token.lexeme;
      var element = tokenToElementMap[token];
      if (element != null) {
        var elementId = _elementIds.putIfAbsent(
          element,
          () => _elementIds.length,
        );
        tokenString += '#$elementId';
      }
      return tokenString;
    });

    const separator = '\uFFFF';
    return tokensWithId.join(separator) + separator;
  }
}

/// [RecursiveAstVisitor] that delegates visit methods to functions.
class _FunctionAstVisitor extends RecursiveAstVisitor<void> {
  final void Function(SimpleIdentifier)? simpleIdentifier;

  _FunctionAstVisitor({
    this.simpleIdentifier,
  });

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    if (simpleIdentifier != null) {
      simpleIdentifier!(node);
    }
    super.visitSimpleIdentifier(node);
  }
}

class _OccurrencesVisitor extends GeneralizingAstVisitor<void> {
  final _ExpressionEncoder encoder;
  final List<SourceRange> occurrences;
  final String searchCode;

  _OccurrencesVisitor(this.encoder, this.occurrences, this.searchCode);

  @override
  void visitExpression(Expression node) {
    var nodeCode = encoder.encode(node);
    if (nodeCode == searchCode) {
      occurrences.add(range.node(node));
    }
    super.visitExpression(node);
  }
}
