// Copyright (c) 2022, 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/assist.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/utilities/extensions/range_factory.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/source/source_range.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/range_factory.dart';

class ConvertToSuperParameters extends CorrectionProducer {
  @override
  AssistKind get assistKind => DartAssistKind.CONVERT_TO_SUPER_PARAMETERS;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    if (!libraryElement.featureSet.isEnabled(Feature.super_parameters)) {
      // If the library doesn't support super_parameters then the change isn't
      // appropriate.
      return;
    }
    var constructor = _findConstructor();
    if (constructor == null) {
      // If this isn't a constructor declaration then the change isn't
      // appropriate.
      return;
    }
    var superInvocation = _superInvocation(constructor);
    if (superInvocation == null) {
      // If there isn't an explicit invocation of a super constructor then the
      // change isn't appropriate. Note that this also rules out factory
      // constructors because factory constructors can't have initializers.
      return;
    }
    var superConstructor = superInvocation.staticElement;
    if (superConstructor == null) {
      // If the super constructor wasn't resolved then we can't apply the
      // change.
      return;
    }
    // Find the arguments that can be converted. Named arguments are added to
    // [named]. Positional arguments are added to [positional], but the list is
    // set to `null` if a positional argument is found that can't be converted
    // because either all of the positional parameters must be converted or none
    // of them can be converted.
    var parameterMap = _parameterMap(constructor.parameters);
    List<_ParameterData>? positional = [];
    var named = <_ParameterData>[];
    var arguments = superInvocation.argumentList.arguments;
    for (var argumentIndex = 0;
        argumentIndex < arguments.length;
        argumentIndex++) {
      var argument = arguments[argumentIndex];
      if (argument is NamedExpression) {
        var parameterAndElement =
            _parameterFor(parameterMap, argument.expression);
        if (parameterAndElement != null && parameterAndElement.isNamed) {
          var data = _dataForParameter(
            parameterAndElement.parameter,
            parameterAndElement.element,
            argumentIndex,
            argument.staticParameterElement,
          );
          if (data != null) {
            named.add(data);
          }
        }
      } else if (positional != null) {
        var parameterAndElement = _parameterFor(parameterMap, argument);
        if (parameterAndElement == null || !parameterAndElement.isPositional) {
          positional = null;
        } else {
          var data = _dataForParameter(
            parameterAndElement.parameter,
            parameterAndElement.element,
            argumentIndex,
            argument.staticParameterElement,
          );
          if (data == null) {
            positional = null;
          } else {
            positional.add(data);
          }
        }
      }
    }
    if (positional != null && !_inOrder(positional)) {
      positional = null;
    }
    // At this point:
    // 1. `positional` will be `null` if
    //    - there is at least one positional argument that can't be converted,
    //      which implies that there are no positional arguments that can be
    //      converted, or
    //    - if the order of the positional parameters doesn't match the order of
    //      the positional arguments.
    // 2. `positional` will be empty if there are no positional arguments at
    //    all.
    // 3. `named` will be empty if there are no named arguments that can be
    //    converted.
    if ((positional == null || positional.isEmpty) && named.isEmpty) {
      // There are no parameters that can be converted.
      return;
    }

    var allParameters = <_ParameterData>[...?positional, ...named];

    var argumentsToDelete =
        allParameters.map((data) => data.argumentIndex).toList();
    argumentsToDelete.sort();

    await builder.addDartFileEdit(file, (builder) {
      // Convert the parameters.
      for (var parameterData in allParameters) {
        var typeToDelete = parameterData.typeToDelete;
        if (typeToDelete == null) {
          builder.addSimpleInsertion(parameterData.nameOffset, 'super.');
        } else {
          var primaryRange = typeToDelete.primaryRange;
          if (primaryRange == null) {
            builder.addSimpleInsertion(parameterData.nameOffset, 'super.');
          } else {
            builder.addSimpleReplacement(primaryRange, 'super.');
          }
          var parameterRange = typeToDelete.parameterRange;
          if (parameterRange != null) {
            builder.addDeletion(parameterRange);
          }
        }
        var defaultValueRange = parameterData.defaultValueRange;
        if (defaultValueRange != null) {
          builder.addDeletion(defaultValueRange);
        }
      }

      // Remove the corresponding arguments.
      if (argumentsToDelete.length == arguments.length &&
          superInvocation.constructorName == null) {
        var initializers = constructor.initializers;
        SourceRange initializerRange;
        if (initializers.length == 1) {
          initializerRange =
              range.endEnd(constructor.parameters, superInvocation);
        } else {
          initializerRange = range.nodeInList(initializers, superInvocation);
        }
        builder.addDeletion(initializerRange);
      } else {
        var ranges = range.nodesInList(arguments, argumentsToDelete);
        for (var range in ranges) {
          builder.addDeletion(range);
        }
      }
    });
  }

  /// If the [parameter] can be converted into a super initializing formal
  /// parameter then return the data needed to do so.
  _ParameterData? _dataForParameter(
      _Parameter parameter,
      ParameterElement thisParameter,
      int argumentIndex,
      ParameterElement? superParameter) {
    if (superParameter == null) {
      return null;
    }
    // If the type of the `thisParameter` isn't a subtype of the type of the
    // super parameter, then the change isn't appropriate.
    var superType = superParameter.type;
    var thisType = thisParameter.type;
    if (!typeSystem.isSubtypeOf(thisType, superType)) {
      return null;
    }
    var identifier = parameter.parameter.identifier;
    if (identifier == null) {
      // This condition should never occur, but the test is here to promote the
      // type.
      return null;
    }
    // Return the data.
    return _ParameterData(
      argumentIndex: argumentIndex,
      defaultValueRange: _defaultValueRange(
          parameter.parameter, superParameter, thisParameter),
      nameOffset: identifier.offset,
      parameterIndex: parameter.index,
      typeToDelete: superType == thisType ? _type(parameter.parameter) : null,
    );
  }

  /// Return the range of the default value associated with the [parameter], or
  /// `null` if the parameter doesn't have a default value or if the default
  /// value is not the same as the default value in the super constructor.
  SourceRange? _defaultValueRange(FormalParameter parameter,
      ParameterElement superParameter, ParameterElement thisParameter) {
    if (parameter is DefaultFormalParameter) {
      var defaultValue = parameter.defaultValue;
      if (defaultValue != null) {
        var superDefault = superParameter.computeConstantValue();
        var thisDefault = thisParameter.computeConstantValue();
        if (superDefault != null && superDefault == thisDefault) {
          return range.endEnd(parameter.identifier!, defaultValue);
        }
      }
    }
    return null;
  }

  /// Return the constructor to be converted, or `null` if the cursor is not on
  /// the name of a constructor.
  ConstructorDeclaration? _findConstructor() {
    final node = this.node;
    if (node is SimpleIdentifier) {
      var parent = node.parent;
      if (parent is ConstructorDeclaration) {
        return parent;
      } else if (parent is ConstructorName) {
        var grandparent = parent.parent;
        if (grandparent is ConstructorDeclaration) {
          return grandparent;
        }
      }
    }
    return null;
  }

  /// Return `true` if the given list of [parameterData] is in order by the
  /// index of the parameters. The list is known to be in order by the argument
  /// positions, so this test is used to ensure that the order won't be changed
  /// if the parameters are converted.
  bool _inOrder(List<_ParameterData> parameterData) {
    var previousIndex = -1;
    for (var data in parameterData) {
      var index = data.parameterIndex;
      if (index < previousIndex) {
        return false;
      }
      previousIndex = index;
    }
    return true;
  }

  /// Return the parameter element corresponding to the [expression], or `null`
  /// if the expression isn't a simple reference to one of the parameters in the
  /// constructor being converted.
  _ParameterAndElement? _parameterFor(
      Map<ParameterElement, _Parameter> parameterMap, Expression expression) {
    if (expression is SimpleIdentifier) {
      var element = expression.staticElement;
      var parameter = parameterMap[element];
      if (element is ParameterElement && parameter != null) {
        return _ParameterAndElement(element, parameter);
      }
    }
    return null;
  }

  /// Return a map from parameter elements to the parameters that define those
  /// elements.
  Map<ParameterElement, _Parameter> _parameterMap(
      FormalParameterList parameterList) {
    var map = <ParameterElement, _Parameter>{};
    var parameters = parameterList.parameters;
    for (var i = 0; i < parameters.length; i++) {
      var parameter = parameters[i];
      var element = parameter.declaredElement;
      if (element != null) {
        map[element] = _Parameter(parameter, i);
      }
    }
    return map;
  }

  /// Return the invocation of the super constructor.
  SuperConstructorInvocation? _superInvocation(
      ConstructorDeclaration constructor) {
    var initializers = constructor.initializers;
    // Search all of the initializers in case the code is invalid, but start
    // from the end because the code will usually be correct.
    for (var i = initializers.length - 1; i >= 0; i--) {
      var initializer = initializers[i];
      if (initializer is SuperConstructorInvocation) {
        return initializer;
      }
    }
    return null;
  }

  /// Return data about the type annotation on the [parameter]. This is the
  /// information about the ranges of text that need to be removed in order to
  /// remove the type annotation.
  _TypeData? _type(FormalParameter parameter) {
    if (parameter is DefaultFormalParameter) {
      return _type(parameter.parameter);
    } else if (parameter is SimpleFormalParameter) {
      var typeAnnotation = parameter.type;
      if (typeAnnotation != null) {
        return _TypeData(
            primaryRange:
                range.startStart(typeAnnotation, parameter.identifier!));
      }
    } else if (parameter is FunctionTypedFormalParameter) {
      var returnType = parameter.returnType;
      return _TypeData(
          primaryRange: returnType != null
              ? range.startStart(returnType, parameter.identifier)
              : null,
          parameterRange: range.node(parameter.parameters));
    }
    return null;
  }

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

/// Information about a single parameter.
class _Parameter {
  final FormalParameter parameter;

  final int index;

  _Parameter(this.parameter, this.index);
}

/// A data class used to avoid a null check.
class _ParameterAndElement {
  final ParameterElement element;

  final _Parameter parameter;

  _ParameterAndElement(this.element, this.parameter);

  bool get isNamed => element.isNamed;

  bool get isPositional => element.isPositional;
}

/// Information used to convert a single parameter.
class _ParameterData {
  /// The type annotation that should be deleted from the parameter list, or
  /// `null` if there is no type annotation to delete or if the type should not
  /// be deleted.
  final _TypeData? typeToDelete;

  /// The offset of the name.
  final int nameOffset;

  /// The range of the default value that is to be deleted from the parameter
  /// list, or `null` if there is no default value, the default value isn't to
  /// be deleted.
  final SourceRange? defaultValueRange;

  /// The index of the parameter to be updated.
  final int parameterIndex;

  /// The index of the argument to be deleted.
  final int argumentIndex;

  /// Initialize a newly create data object.
  _ParameterData(
      {required this.typeToDelete,
      required this.nameOffset,
      required this.defaultValueRange,
      required this.parameterIndex,
      required this.argumentIndex});
}

/// Information about the ranges of text that need to be removed in order to
/// remove a type annotation.
class _TypeData {
  SourceRange? primaryRange;

  SourceRange? parameterRange;

  _TypeData({required this.primaryRange, this.parameterRange});
}
