// 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: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/element/element.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' show Position;
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 CreateMethod extends CorrectionProducer {
  /// The kind of method to be created.
  final _MethodKind _kind;

  String _memberName;

  CreateMethod(this._kind);

  @override
  List<Object> get fixArguments => [_memberName];

  @override
  FixKind get fixKind => DartFixKind.CREATE_METHOD;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    if (_kind == _MethodKind.equalsOrHashCode) {
      await createEqualsOrHashCode(builder);
    } else if (_kind == _MethodKind.method) {
      await createMethod(builder);
    }
  }

  Future<void> createEqualsOrHashCode(ChangeBuilder builder) async {
    final methodDecl = node.thisOrAncestorOfType<MethodDeclaration>();
    final classDecl = methodDecl.thisOrAncestorOfType<ClassDeclaration>();
    if (methodDecl != null && classDecl != null) {
      final classElement = classDecl.declaredElement;

      ExecutableElement element;
      if (methodDecl.name.name == 'hashCode') {
        _memberName = '==';
        element = classElement.lookUpInheritedMethod(
            _memberName, classElement.library);
      } else {
        _memberName = 'hashCode';
        element = classElement.lookUpInheritedConcreteGetter(
            _memberName, classElement.library);
      }

      final location =
          utils.prepareNewClassMemberLocation(classDecl, (_) => true);

      await builder.addDartFileEdit(file, (fileBuilder) {
        fileBuilder.addInsertion(location.offset, (builder) {
          builder.write(location.prefix);
          builder.writeOverride(element, invokeSuper: true);
          builder.write(location.suffix);
        });
      });

      builder.setSelection(Position(file, location.offset));
    }
  }

  Future<void> createMethod(ChangeBuilder builder) async {
    if (node is! SimpleIdentifier || node.parent is! MethodInvocation) {
      return;
    }
    _memberName = (node as SimpleIdentifier).name;
    var invocation = node.parent as MethodInvocation;
    // prepare environment
    Element targetElement;
    var staticModifier = false;

    CompilationUnitMember targetNode;
    var target = invocation.realTarget;
    var utils = this.utils;
    if (target is ExtensionOverride) {
      targetElement = target.staticElement;
      targetNode = await getExtensionDeclaration(targetElement);
      if (targetNode == null) {
        return;
      }
    } else if (target is Identifier &&
        target.staticElement is ExtensionElement) {
      targetElement = target.staticElement;
      targetNode = await getExtensionDeclaration(targetElement);
      if (targetNode == null) {
        return;
      }
      staticModifier = true;
    } else if (target == null) {
      targetElement = unit.declaredElement;
      var enclosingMember = node.thisOrAncestorOfType<ClassMember>();
      if (enclosingMember == null) {
        // If the undefined identifier isn't inside a class member, then it
        // doesn't make sense to create a method.
        return;
      }
      targetNode = enclosingMember.parent;
      staticModifier = inStaticContext;
    } else {
      var targetClassElement = getTargetClassElement(target);
      if (targetClassElement == null) {
        return;
      }
      targetElement = targetClassElement;
      if (targetClassElement.librarySource.isInSystemLibrary) {
        return;
      }
      // prepare target ClassDeclaration
      targetNode = await getClassOrMixinDeclaration(targetClassElement);
      if (targetNode == null) {
        return;
      }
      // maybe static
      if (target is Identifier) {
        staticModifier = target.staticElement.kind == ElementKind.CLASS;
      }
      // use different utils
      var targetPath = targetClassElement.source.fullName;
      var targetResolveResult =
          await resolvedResult.session.getResolvedUnit(targetPath);
      utils = CorrectionUtils(targetResolveResult);
    }
    var targetLocation = utils.prepareNewMethodLocation(targetNode);
    var targetFile = targetElement.source.fullName;
    // build method source
    await builder.addDartFileEdit(targetFile, (builder) {
      builder.addInsertion(targetLocation.offset, (builder) {
        builder.write(targetLocation.prefix);
        // maybe "static"
        if (staticModifier) {
          builder.write('static ');
        }
        // append return type
        {
          var type = inferUndefinedExpressionType(invocation);
          if (builder.writeType(type, groupName: 'RETURN_TYPE')) {
            builder.write(' ');
          }
        }
        // append name
        builder.addLinkedEdit('NAME', (builder) {
          builder.write(_memberName);
        });
        builder.write('(');
        builder.writeParametersMatchingArguments(invocation.argumentList);
        builder.write(') {}');
        builder.write(targetLocation.suffix);
      });
      if (targetFile == file) {
        builder.addLinkedPosition(range.node(node), 'NAME');
      }
    });
  }

  /// Return an instance of this class that will create either an equals
  /// (operator =) or `hashCode` method based on the existing other half of the
  /// pair. Used as a tear-off in `FixProcessor`.
  static CreateMethod equalsOrHashCode() =>
      CreateMethod(_MethodKind.equalsOrHashCode);

  /// Return an instance of this class that will create a method based on an
  /// invocation of an undefined method. Used as a tear-off in `FixProcessor`.
  static CreateMethod method() => CreateMethod(_MethodKind.method);
}

/// A representation of the kind of element that should be suggested.
enum _MethodKind {
  equalsOrHashCode,
  method,
}
