// 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class AddTypeAnnotation extends CorrectionProducer {
  @override
  AssistKind get assistKind => DartAssistKind.ADD_TYPE_ANNOTATION;

  @override
  FixKind get fixKind => DartFixKind.ADD_TYPE_ANNOTATION;

  @override
  Future<void> compute(DartChangeBuilder builder) async {
    var node = this.node;
    if (node is SimpleIdentifier) {
      var parent = node.parent;
      if (parent is SimpleFormalParameter) {
        await _forSimpleFormalParameter(builder, node, parent);
        return;
      }
    }
    while (node != null) {
      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 (forLoopParts.iterable != null &&
              offset < forLoopParts.iterable.offset) {
            if (forLoopParts is ForEachPartsWithDeclaration) {
              await _forDeclaredIdentifier(builder, forLoopParts.loopVariable);
            }
          }
        }
        return;
      }
      node = node.parent;
    }
  }

  /// 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(
      DartChangeBuilder 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;
    }
    _configureTargetLocation(node);

    Future<bool> applyChange(DartChangeBuilder builder) async {
      var validChange = true;
      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
        var keyword = declaredIdentifier.keyword;
        if (keyword.keyword == Keyword.VAR) {
          builder.addReplacement(range.token(keyword),
              (DartEditBuilder builder) {
            validChange = builder.writeType(type);
          });
        } else {
          builder.addInsertion(declaredIdentifier.identifier.offset,
              (DartEditBuilder builder) {
            validChange = builder.writeType(type);
            builder.write(' ');
          });
        }
      });
      return validChange;
    }

    if (await applyChange(_temporaryBuilder(builder))) {
      await applyChange(builder);
    }
  }

  Future<void> _forSimpleFormalParameter(DartChangeBuilder 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;
    }
    _configureTargetLocation(node);

    Future<bool> applyChange(DartChangeBuilder builder) async {
      var validChange = true;
      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
        builder.addInsertion(name.offset, (DartEditBuilder builder) {
          validChange = builder.writeType(type);
          if (validChange) {
            builder.write(' ');
          }
        });
      });
      return validChange;
    }

    if (await applyChange(_temporaryBuilder(builder))) {
      await applyChange(builder);
    }
  }

  Future<void> _forVariableDeclaration(DartChangeBuilder builder,
      VariableDeclarationList declarationList) async {
    // Ensure that there isn't already a type annotation.
    if (declarationList.type != null) {
      return;
    }
    // Ensure that there is a single VariableDeclaration.
    List<VariableDeclaration> variables = declarationList.variables;
    if (variables.length != 1) {
      return;
    }
    var 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.
    var initializer = variable.initializer;
    if (initializer == null) {
      return;
    }
    var type = initializer.staticType;
    // prepare type source
    if ((type is! InterfaceType || type.isDartCoreNull) &&
        type is! FunctionType) {
      return;
    }
    _configureTargetLocation(node);

    Future<bool> applyChange(DartChangeBuilder builder) async {
      var validChange = true;
      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
        var keyword = declarationList.keyword;
        if (keyword?.keyword == Keyword.VAR) {
          builder.addReplacement(range.token(keyword),
              (DartEditBuilder builder) {
            validChange = builder.writeType(type);
          });
        } else {
          builder.addInsertion(variable.offset, (DartEditBuilder builder) {
            validChange = builder.writeType(type);
            builder.write(' ');
          });
        }
      });
      return validChange;
    }

    if (await applyChange(_temporaryBuilder(builder))) {
      await applyChange(builder);
    }
  }

  DartChangeBuilder _temporaryBuilder(DartChangeBuilder builder) =>
      DartChangeBuilderImpl.forWorkspace(
          (builder as DartChangeBuilderImpl).workspace);
}
