// 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/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';

class CreateConstructorForFinalFields extends CorrectionProducer {
  @override
  FixKind get fixKind => DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    if (node is! SimpleIdentifier || node.parent is! VariableDeclaration) {
      return;
    }

    var classDeclaration = node.thisOrAncestorOfType<ClassDeclaration>();
    if (classDeclaration == null) {
      return;
    }

    var className = classDeclaration.name.name;
    var superType = classDeclaration.declaredElement?.supertype;
    if (superType == null) {
      return;
    }

    var variableLists = <VariableDeclarationList>[];
    for (var member in classDeclaration.members) {
      if (member is FieldDeclaration) {
        var variableList = member.fields;
        if (variableList.isFinal && !variableList.isLate) {
          variableLists.add(variableList);
        }
      }
    }
    // prepare location for a new constructor
    var targetLocation = utils.prepareNewConstructorLocation(
        resolvedResult.session, classDeclaration);
    if (targetLocation == null) {
      return;
    }

    if (flutter.isExactlyStatelessWidgetType(superType) ||
        flutter.isExactlyStatefulWidgetType(superType)) {
      // Specialize for Flutter widgets.
      var keyClass = await sessionHelper.getClass(flutter.widgetsUri, 'Key');
      if (keyClass == null) {
        return;
      }

      if (unit.featureSet.isEnabled(Feature.super_parameters)) {
        await _withSuperParameters(
            builder, targetLocation, className, variableLists);
      } else {
        await _withoutSuperParameters(
            builder, targetLocation, className, keyClass, variableLists);
      }
    } else {
      var fieldNames = <String>[];
      for (var variableList in variableLists) {
        fieldNames.addAll(variableList.variables
            .where((v) => v.initializer == null)
            .map((v) => v.name.name));
      }

      await builder.addDartFileEdit(file, (builder) {
        builder.addInsertion(targetLocation.offset, (builder) {
          builder.write(targetLocation.prefix);
          builder.writeConstructorDeclaration(className,
              fieldNames: fieldNames);
          builder.write(targetLocation.suffix);
        });
      });
    }
  }

  Future<void> _withoutSuperParameters(
      ChangeBuilder builder,
      ClassMemberLocation targetLocation,
      String className,
      ClassElement keyClass,
      List<VariableDeclarationList> variableLists) async {
    var isNonNullable = unit.featureSet.isEnabled(Feature.non_nullable);
    await builder.addDartFileEdit(file, (builder) {
      builder.addInsertion(targetLocation.offset, (builder) {
        builder.write(targetLocation.prefix);
        builder.write('const ');
        builder.write(className);
        builder.write('({');
        builder.writeType(
          keyClass.instantiate(
            typeArguments: const [],
            nullabilitySuffix: isNonNullable
                ? NullabilitySuffix.question
                : NullabilitySuffix.star,
          ),
        );
        builder.write(' key');

        _writeParameters(builder, variableLists, isNonNullable);

        builder.write('}) : super(key: key);');
        builder.write(targetLocation.suffix);
      });
    });
  }

  Future<void> _withSuperParameters(
      ChangeBuilder builder,
      ClassMemberLocation targetLocation,
      String className,
      List<VariableDeclarationList> variableLists) async {
    await builder.addDartFileEdit(file, (builder) {
      builder.addInsertion(targetLocation.offset, (builder) {
        builder.write(targetLocation.prefix);
        builder.write('const ');
        builder.write(className);
        builder.write('({');
        builder.write('super.key');

        _writeParameters(builder, variableLists, true);

        builder.write('});');
        builder.write(targetLocation.suffix);
      });
    });
  }

  void _writeParameters(DartEditBuilder builder,
      List<VariableDeclarationList> variableLists, bool isNonNullable) {
    var childrenFields = <String>[];
    var childrenNullables = <bool>[];
    for (var variableList in variableLists) {
      var fieldNames = variableList.variables
          .where((v) => v.initializer == null)
          .map((v) => v.name.name);

      for (var fieldName in fieldNames) {
        if (fieldName == 'child' || fieldName == 'children') {
          childrenFields.add(fieldName);
          childrenNullables.add(variableList.type?.type?.nullabilitySuffix ==
              NullabilitySuffix.question);
          continue;
        }
        builder.write(', ');
        if (isNonNullable &&
            variableList.type?.type?.nullabilitySuffix !=
                NullabilitySuffix.question) {
          builder.write('required ');
        }
        builder.write('this.');
        builder.write(fieldName);
      }
    }
    for (var i = 0; i < childrenFields.length; i++) {
      var fieldName = childrenFields[i];
      var nullableField = childrenNullables[i];
      builder.write(', ');
      if (isNonNullable && !nullableField) {
        builder.write('required ');
      }
      builder.write('this.');
      builder.write(fieldName);
    }
  }

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