// Copyright (c) 2020, 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:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:analysis_server/src/services/correction/assist.dart';
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/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer_plugin/utilities/assist/assist.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 AddTypeAnnotation extends CorrectionProducer {
  @override
  bool canBeAppliedInBulk;

  @override
  bool canBeAppliedToFile;

  AddTypeAnnotation(bool multi)
      : canBeAppliedInBulk = multi,
        canBeAppliedToFile = multi;

  @override
  AssistKind get assistKind => DartAssistKind.ADD_TYPE_ANNOTATION;

  @override
  FixKind get fixKind => DartFixKind.ADD_TYPE_ANNOTATION;

  @override
  FixKind get multiFixKind => DartFixKind.ADD_TYPE_ANNOTATION_MULTI;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    final node = this.node;
    if (node is SimpleIdentifier) {
      var parent = node.parent;
      if (parent is SimpleFormalParameter) {
        await _forSimpleFormalParameter(builder, node, parent);
        return;
      }
    }

    for (var node in this.node.withParents) {
      if (node is VariableDeclarationList) {
        await _forVariableDeclaration(builder, node);
        return;
      } else if (node is DeclaredIdentifier) {
        await _forDeclaredIdentifier(builder, node);
        return;
      } else if (node is ForStatement) {
        var forLoopParts = node.forLoopParts;
        if (forLoopParts is ForEachParts) {
          var offset = this.node.offset;
          if (offset < forLoopParts.iterable.offset) {
            if (forLoopParts is ForEachPartsWithDeclaration) {
              await _forDeclaredIdentifier(builder, forLoopParts.loopVariable);
            }
          }
        }
        return;
      }
    }
  }

  Future<void> _applyChange(
      ChangeBuilder builder, Token? keyword, int offset, DartType type) async {
    _configureTargetLocation(node);

    await builder.addDartFileEdit(file, (builder) {
      if (builder.canWriteType(type)) {
        if (keyword != null && keyword.keyword == Keyword.VAR) {
          builder.addReplacement(range.token(keyword), (builder) {
            builder.writeType(type);
          });
        } else {
          builder.addInsertion(offset, (builder) {
            builder.writeType(type);
            builder.write(' ');
          });
        }
      }
    });
  }

  /// Configure the [utils] using the given [target].
  void _configureTargetLocation(Object target) {
    utils.targetClassElement = null;
    if (target is AstNode) {
      var targetClassDeclaration =
          target.thisOrAncestorOfType<ClassDeclaration>();
      if (targetClassDeclaration != null) {
        utils.targetClassElement = targetClassDeclaration.declaredElement;
      }
    }
  }

  Future<void> _forDeclaredIdentifier(
      ChangeBuilder builder, DeclaredIdentifier declaredIdentifier) async {
    // Ensure that there isn't already a type annotation.
    if (declaredIdentifier.type != null) {
      return;
    }
    var type = declaredIdentifier.declaredElement!.type;
    if (type is! InterfaceType && type is! FunctionType) {
      return;
    }
    await _applyChange(builder, declaredIdentifier.keyword,
        declaredIdentifier.identifier.offset, type);
  }

  Future<void> _forSimpleFormalParameter(ChangeBuilder builder,
      SimpleIdentifier name, SimpleFormalParameter parameter) async {
    // Ensure that there isn't already a type annotation.
    if (parameter.type != null) {
      return;
    }
    // Prepare the type.
    var type = parameter.declaredElement!.type;
    // TODO(scheglov) If the parameter is in a method declaration, and if the
    // method overrides a method that has a type for the corresponding
    // parameter, it would be nice to copy down the type from the overridden
    // method.
    if (type is! InterfaceType) {
      return;
    }
    await _applyChange(builder, null, name.offset, type);
  }

  Future<void> _forVariableDeclaration(
      ChangeBuilder builder, VariableDeclarationList declarationList) async {
    // Ensure that there isn't already a type annotation.
    if (declarationList.type != null) {
      return;
    }
    final variables = declarationList.variables;
    final variable = variables[0];
    // Ensure that the selection is not after the name of the variable.
    if (selectionOffset > variable.name.end) {
      return;
    }
    // Ensure that there is an initializer to get the type from.
    final type = _typeForVariable(variable);
    if (type == null) {
      return;
    }
    // Ensure that there is a single type.
    for (var i = 1; i < variables.length; i++) {
      if (_typeForVariable(variables[i]) != type) {
        return;
      }
    }
    if ((type is! InterfaceType || type.isDartCoreNull) &&
        type is! FunctionType) {
      return;
    }
    await _applyChange(builder, declarationList.keyword, variable.offset, type);
  }

  DartType? _typeForVariable(VariableDeclaration variable) {
    var initializer = variable.initializer;
    if (initializer != null) {
      return initializer.staticType;
    }
    // The parents should be a [VariableDeclarationList],
    // [VariableDeclarationStatement], and [Block], in that order.
    var statement = variable.parent?.parent;
    var block = statement?.parent;
    if (statement is! VariableDeclarationStatement || block is! Block) {
      return null;
    }
    var element = variable.declaredElement;
    if (element is! LocalVariableElement) {
      return null;
    }
    var statements = block.statements;
    var index = statements.indexOf(statement);
    var visitor = _AssignedTypeCollector(typeSystem, element);
    for (var i = index + 1; i < statements.length; i++) {
      statements[i].accept(visitor);
    }
    return visitor.bestType;
  }

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

  /// Return an instance of this class that can apply bulk and in-file fixes.
  /// Used as a tear-off in `FixProcessor`.
  static AddTypeAnnotation newInstanceBulkFixable() => AddTypeAnnotation(true);
}

class _AssignedTypeCollector extends RecursiveAstVisitor<void> {
  /// The type system used to compute the best type.
  final TypeSystem typeSystem;

  final LocalVariableElement variable;

  /// The types that are assigned to the variable.
  final Set<DartType> assignedTypes = {};

  _AssignedTypeCollector(this.typeSystem, this.variable);

  DartType? get bestType {
    if (assignedTypes.isEmpty) {
      return null;
    }
    var types = assignedTypes.toList();
    var bestType = types[0];
    for (var i = 1; i < assignedTypes.length; i++) {
      bestType = typeSystem.leastUpperBound(bestType, types[i]);
    }
    return bestType;
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    var leftHandSide = node.leftHandSide;
    if (leftHandSide is SimpleIdentifier &&
        leftHandSide.staticElement == variable) {
      var type = node.rightHandSide.staticType;
      if (type != null) {
        assignedTypes.add(type);
      }
    }
    return super.visitAssignmentExpression(node);
  }
}
