// 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/data_driven.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:meta/meta.dart';

/// The addition of a new parameter.
class AddParameter extends ParameterModification {
  /// The index of the parameter in the parameter list after the modifications
  /// have been applied.
  final int index;

  /// The name of the parameter that was added.
  final String name;

  /// A flag indicating whether the parameter is a required parameter.
  final bool isRequired;

  /// A flag indicating whether the parameter is a positional parameter.
  final bool isPositional;

  /// The code template used to compute the value of the new argument in
  /// invocations of the function, or `null` if the parameter is optional and no
  /// argument needs to be added. The only time an argument needs to be added
  /// for an optional parameter is if the parameter is positional and there are
  /// pre-existing optional positional parameters after the ones being added.
  final CodeTemplate argumentValue;

  /// Initialize a newly created parameter modification to represent the
  /// addition of a parameter. If provided, the [argumentValue] will be used as
  /// the value of the new argument in invocations of the function.
  AddParameter(this.index, this.name, this.isRequired, this.isPositional,
      this.argumentValue)
      : assert(index >= 0),
        assert(name != null);
}

/// The data related to an executable element whose parameters have been
/// modified.
class ModifyParameters extends Change<_Data> {
  /// A list of the modifications being made.
  final List<ParameterModification> modifications;

  /// Initialize a newly created transform to modifications to the parameter
  /// list of a function.
  ModifyParameters({@required this.modifications})
      : assert(modifications != null),
        assert(modifications.isNotEmpty);

  @override
  void apply(DartFileEditBuilder builder, DataDrivenFix fix, _Data data) {
    var argumentList = data.argumentList;
    var arguments = argumentList.arguments;
    var argumentCount = arguments.length;
    var newNamed = <AddParameter>[];
    var indexToNewArgumentMap = <int, AddParameter>{};
    var argumentsToInsert = <int>[];
    var argumentsToDelete = <int>[];
    var remainingArguments = [for (var i = 0; i < argumentCount; i++) i];
    for (var modification in modifications) {
      if (modification is AddParameter) {
        var index = modification.index;
        indexToNewArgumentMap[index] = modification;
        if (modification.isPositional) {
          argumentsToInsert.add(index);
        } else if (modification.isRequired) {
          newNamed.add(modification);
        }
      } else if (modification is RemoveParameter) {
        var argument = modification.parameter.argumentFrom(argumentList);
        // If there is no argument corresponding to the parameter then we assume
        // that the parameter was optional (and absent) and don't try to remove
        // it.
        if (argument != null) {
          var index = arguments.indexOf(_realArgument(argument));
          argumentsToDelete.add(index);
          remainingArguments.remove(index);
        }
      }
    }
    argumentsToInsert.sort();
    newNamed.sort((first, second) => first.name.compareTo(second.name));

    /// Write to the [builder] the argument associated with a single
    /// [parameter].
    void writeArgument(DartEditBuilder builder, AddParameter parameter) {
      if (!parameter.isPositional) {
        builder.write(parameter.name);
        builder.write(': ');
      }
      parameter.argumentValue
          .writeOn(builder, TemplateContext(argumentList.parent, fix.utils));
    }

    var insertionRanges = argumentsToInsert.contiguousSubRanges.toList();
    var deletionRanges = argumentsToDelete.contiguousSubRanges.toList();
    if (insertionRanges.isNotEmpty) {
      /// Write to the [builder] the new arguments in the [insertionRange]. If
      /// [needsInitialComma] is `true` then we need to write a comma before the
      /// first of the new arguments.
      void writeInsertionRange(DartEditBuilder builder,
          _IndexRange insertionRange, bool needsInitialComma) {
        var needsComma = needsInitialComma;
        for (var argumentIndex = insertionRange.lower;
            argumentIndex <= insertionRange.upper;
            argumentIndex++) {
          if (needsComma) {
            builder.write(', ');
          } else {
            needsComma = true;
          }
          var parameter = indexToNewArgumentMap[argumentIndex];
          writeArgument(builder, parameter);
        }
      }

      var nextRemaining = 0;
      var nextInsertionRange = 0;
      var insertionCount = 0;
      while (nextRemaining < remainingArguments.length &&
          nextInsertionRange < insertionRanges.length) {
        var remainingIndex = remainingArguments[nextRemaining];
        var insertionRange = insertionRanges[nextInsertionRange];
        var insertionIndex = insertionRange.lower;
        if (insertionIndex <= remainingIndex + insertionCount) {
          // There are arguments that need to be inserted before the next
          // remaining argument.
          var deletionRange =
              _rangeContaining(deletionRanges, insertionIndex - 1);
          if (deletionRange == null) {
            // The insertion range doesn't overlap a deletion range, so insert
            // the added arguments before the argument whose index is
            // `remainingIndex`.
            int offset;
            var needsInitialComma = false;
            if (insertionIndex > 0) {
              offset = arguments[remainingIndex - 1].end;
              needsInitialComma = true;
            } else {
              offset = arguments[remainingIndex].offset;
            }
            builder.addInsertion(offset, (builder) {
              writeInsertionRange(builder, insertionRange, needsInitialComma);
              if (insertionIndex == 0) {
                builder.write(', ');
              }
            });
          } else {
            // The insertion range overlaps a deletion range, so replace the
            // arguments in the deletion range with the arguments in the
            // insertion range.
            var replacementRange = range.argumentRange(
                argumentList, deletionRange.lower, deletionRange.upper, false);
            builder.addReplacement(replacementRange, (builder) {
              writeInsertionRange(builder, insertionRange, false);
            });
            deletionRanges.remove(deletionRange);
          }
          insertionCount += insertionRange.count;
          nextInsertionRange++;
        } else {
          // There are no arguments that need to be inserted before the next
          // remaining argument, so just move past the next remaining argument.
          nextRemaining++;
        }
      }
      // The remaining insertion ranges might include new required arguments
      // that need to be inserted after the last argument.
      var offset = arguments[arguments.length - 1].end;
      while (nextInsertionRange < insertionRanges.length) {
        var insertionRange = insertionRanges[nextInsertionRange];
        var lower = insertionRange.lower;
        var upper = insertionRange.upper;
        while (upper >= lower && !indexToNewArgumentMap[upper].isRequired) {
          upper--;
        }
        if (upper >= lower) {
          builder.addInsertion(offset, (builder) {
            writeInsertionRange(builder, _IndexRange(lower, upper), true);
          });
        }
        nextInsertionRange++;
      }
    }
    //
    // Insert arguments for required named parameters.
    //
    if (newNamed.isNotEmpty) {
      int offset;
      var needsInitialComma = false;
      if (remainingArguments.isEmpty && argumentsToInsert.isEmpty) {
        offset = argumentList.rightParenthesis.offset;
      } else {
        offset = arguments[arguments.length - 1].end;
        needsInitialComma = true;
      }
      builder.addInsertion(offset, (builder) {
        for (var i = 0; i < newNamed.length; i++) {
          if (i > 0 || needsInitialComma) {
            builder.write(', ');
          }
          writeArgument(builder, newNamed[i]);
        }
      });
    }
    //
    // The remaining deletion ranges are now ready to be removed.
    //
    for (var subRange in deletionRanges) {
      builder.addDeletion(range.argumentRange(
          argumentList, subRange.lower, subRange.upper, true));
    }
  }

  @override
  _Data validate(DataDrivenFix fix) {
    var node = fix.node;
    var parent = node.parent;
    if (parent is InvocationExpression) {
      var argumentList = parent.argumentList;
      return _Data(argumentList);
    } else if (parent is Label) {
      var argumentList = parent.parent.parent;
      if (argumentList is ArgumentList) {
        return _Data(argumentList);
      }
    }
    return null;
  }

  /// Return the range from the list of [ranges] that contains the given
  /// [index], or `null` if there is no such range.
  _IndexRange _rangeContaining(List<_IndexRange> ranges, int index) {
    for (var range in ranges) {
      if (index >= range.lower && index <= range.upper) {
        return range;
      }
    }
    return null;
  }

  /// Return the element of the argument list whose value is the given
  /// [argument]. If the argument is the child of a named expression, then that
  /// will be the named expression, otherwise it will be the argument itself.
  Expression _realArgument(Expression argument) =>
      argument.parent is NamedExpression ? argument.parent : argument;
}

/// A modification related to a parameter.
abstract class ParameterModification {}

/// The removal of an existing parameter.
class RemoveParameter extends ParameterModification {
  /// The parameter that was removed.
  final ParameterReference parameter;

  /// Initialize a newly created parameter modification to represent the removal
  /// of an existing [parameter].
  RemoveParameter(this.parameter) : assert(parameter != null);
}

/// The data returned when updating an invocation site.
class _Data {
  /// The argument list to be updated.
  final ArgumentList argumentList;

  /// Initialize a newly created data object with the data needed to update an
  /// invocation site.
  _Data(this.argumentList);
}

/// A range of indexes within a list.
class _IndexRange {
  /// The index of the first element in the range.
  final int lower;

  /// The index of the last element in the range. This will be the same as the
  /// [lower] if there is a single element in the range.
  final int upper;

  /// Initialize a newly created range.
  _IndexRange(this.lower, this.upper);

  /// Return the number of indices in this range.
  int get count => upper - lower + 1;

  @override
  String toString() => '[$lower..$upper]';
}

extension on List<int> {
  Iterable<_IndexRange> get contiguousSubRanges sync* {
    if (isEmpty) {
      return;
    }
    var lower = this[0];
    var previous = lower;
    var index = 1;
    while (index < length) {
      var current = this[index];
      if (current == previous + 1) {
        previous = current;
      } else {
        yield _IndexRange(lower, previous);
        lower = previous = current;
      }
      index++;
    }
    yield _IndexRange(lower, previous);
  }
}
