// 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/dart/element/type.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 CreateConstructor extends CorrectionProducer {
  /// The name of the constructor being created.
  /// TODO(migration) We set this node when we have the change.
  late String _constructorName;

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

  @override
  FixKind get fixKind => DartFixKind.CREATE_CONSTRUCTOR;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    var node = this.node;
    final argumentList = node.parent is ArgumentList ? node.parent : node;
    if (argumentList is ArgumentList) {
      var instanceCreation = argumentList.parent;
      if (instanceCreation is InstanceCreationExpression) {
        await _proposeFromInstanceCreation(builder, instanceCreation);
      }
    } else {
      if (node is SimpleIdentifier) {
        var parent = node.parent;
        if (parent is ConstructorName) {
          await _proposeFromConstructorName(builder, node, parent);
          return;
        }
      }
      var parent = node.thisOrAncestorOfType<EnumConstantDeclaration>();
      if (parent != null) {
        await _proposeFromEnumConstantDeclaration(builder, parent.name, parent);
      }
    }
  }

  Future<void> _proposeFromConstructorName(ChangeBuilder builder,
      SimpleIdentifier name, ConstructorName constructorName) async {
    InstanceCreationExpression? instanceCreation;
    _constructorName = constructorName.toSource();
    if (constructorName.name == name) {
      var grandParent = constructorName.parent;
      // Type.name
      if (grandParent is InstanceCreationExpression) {
        instanceCreation = grandParent;
        // new Type.name()
        if (grandParent.constructorName != constructorName) {
          return;
        }
      }
    }

    // do we have enough information?
    if (instanceCreation == null) {
      return;
    }

    // prepare target interface type
    var targetType = constructorName.type.type;
    if (targetType is! InterfaceType) {
      return;
    }

    // prepare target ClassDeclaration
    var targetElement = targetType.element;
    var targetResult = await sessionHelper.getElementDeclaration(targetElement);
    if (targetResult == null) {
      return;
    }
    var targetNode = targetResult.node;
    if (targetNode is! ClassDeclaration) {
      return;
    }

    var targetUnit = targetResult.resolvedUnit;
    if (targetUnit == null) {
      return;
    }

    // prepare location
    var targetLocation = CorrectionUtils(targetUnit)
        .prepareNewConstructorLocation(resolvedResult.session, targetNode);
    if (targetLocation == null) {
      return;
    }

    await _write(builder, name, targetElement, targetLocation,
        constructorName: name, argumentList: instanceCreation.argumentList);
  }

  Future<void> _proposeFromEnumConstantDeclaration(ChangeBuilder builder,
      SimpleIdentifier name, EnumConstantDeclaration parent) async {
    var grandParent = parent.parent;
    if (grandParent is! EnumDeclaration) {
      return;
    }
    var targetElement = grandParent.declaredElement;
    if (targetElement == null) {
      return;
    }

    // prepare target interface type
    var targetResult = await sessionHelper.getElementDeclaration(targetElement);
    if (targetResult == null) {
      return;
    }

    var targetNode = targetResult.node;
    if (targetNode is! EnumDeclaration) {
      return;
    }

    var targetUnit = targetResult.resolvedUnit;
    if (targetUnit == null) {
      return;
    }

    // prepare location
    var targetLocation = CorrectionUtils(targetUnit)
        .prepareEnumNewConstructorLocation(targetNode);
    if (targetLocation == null) {
      return;
    }

    var arguments = parent.arguments;
    _constructorName =
        '${targetNode.name}${arguments?.constructorSelector ?? ''}';

    await _write(
      builder,
      name,
      targetElement,
      targetLocation,
      isConst: true,
      constructorName: arguments?.constructorSelector?.name,
      argumentList: arguments?.argumentList,
    );
  }

  Future<void> _proposeFromInstanceCreation(ChangeBuilder builder,
      InstanceCreationExpression instanceCreation) async {
    var constructorName = instanceCreation.constructorName;
    _constructorName = constructorName.toSource();
    // should be synthetic default constructor
    var constructorElement = constructorName.staticElement;
    if (constructorElement == null ||
        !constructorElement.isDefaultConstructor ||
        !constructorElement.isSynthetic) {
      return;
    }

    // prepare target ClassDeclaration
    var targetElement = constructorElement.enclosingElement;
    var targetResult = await sessionHelper.getElementDeclaration(targetElement);
    if (targetResult == null) {
      return;
    }
    var targetNode = targetResult.node;
    if (targetNode is! ClassDeclaration) {
      return;
    }

    var targetUnit = targetResult.resolvedUnit;
    if (targetUnit == null) {
      return;
    }

    // prepare location
    var targetLocation = CorrectionUtils(targetUnit)
        .prepareNewConstructorLocation(resolvedResult.session, targetNode);
    if (targetLocation == null) {
      return;
    }

    var targetSource = targetElement.source;
    var targetFile = targetSource.fullName;
    await builder.addDartFileEdit(targetFile, (builder) {
      builder.addInsertion(targetLocation.offset, (builder) {
        builder.write(targetLocation.prefix);
        builder.writeConstructorDeclaration(targetElement.name,
            argumentList: instanceCreation.argumentList);
        builder.write(targetLocation.suffix);
      });
    });
  }

  Future<void> _write(
    ChangeBuilder builder,
    SimpleIdentifier name,
    ClassElement targetElement,
    InsertionLocation targetLocation, {
    SimpleIdentifier? constructorName,
    bool isConst = false,
    ArgumentList? argumentList,
  }) async {
    var targetFile = targetElement.source.fullName;
    await builder.addDartFileEdit(targetFile, (builder) {
      builder.addInsertion(targetLocation.offset, (builder) {
        builder.write(targetLocation.prefix);
        builder.writeConstructorDeclaration(targetElement.name,
            isConst: isConst,
            argumentList: argumentList,
            constructorName: constructorName,
            constructorNameGroupName: 'NAME');
        builder.write(targetLocation.suffix);
      });
      if (targetFile == file) {
        builder.addLinkedPosition(range.node(name), 'NAME');
      }
    });
  }
}
