// 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/assist.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.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/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class ConvertToSetLiteral extends CorrectionProducer {
  @override
  AssistKind get assistKind => DartAssistKind.CONVERT_TO_SET_LITERAL;

  @override
  bool get canBeAppliedInBulk => true;

  @override
  bool get canBeAppliedToFile => true;

  @override
  FixKind get fixKind => DartFixKind.CONVERT_TO_SET_LITERAL;

  @override
  FixKind get multiFixKind => DartFixKind.CONVERT_TO_SET_LITERAL_MULTI;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    //
    // Check whether this is an invocation of `toSet` on a list literal.
    //
    var invocation = _findInvocationOfToSet();
    if (invocation != null) {
      //
      // Extract the information needed to build the edit.
      //
      var target = invocation.target as ListLiteral;
      var hasTypeArgs = target.typeArguments != null;
      var openRange = range.token(target.leftBracket);
      var closeRange = range.startEnd(target.rightBracket, invocation);
      //
      // Build the change and return the assist.
      //
      await builder.addDartFileEdit(file, (builder) {
        if (hasTypeArgs || _listHasUnambiguousElement(target)) {
          builder.addSimpleReplacement(openRange, '{');
        } else {
          builder.addSimpleReplacement(openRange, '<dynamic>{');
        }
        builder.addSimpleReplacement(closeRange, '}');
      });
      return;
    }
    //
    // Check whether this is one of the constructors defined on `Set`.
    //
    var creation = _findSetCreation();
    if (creation != null) {
      //
      // Extract the information needed to build the edit.
      //
      var name = creation.constructorName.name;
      var constructorTypeArguments =
          creation.constructorName.type.typeArguments;
      TypeArgumentList? elementTypeArguments;
      SourceRange? elementsRange;
      if (name == null) {
        // Handle an invocation of the default constructor `Set()`.
      } else if (name.name == 'from' || name.name == 'of') {
        // Handle an invocation of the constructor `Set.from()` or `Set.of()`.
        var arguments = creation.argumentList.arguments;
        if (arguments.length != 1) {
          return;
        }
        if (arguments[0] is ListLiteral) {
          var elements = arguments[0] as ListLiteral;
          elementTypeArguments = elements.typeArguments;
          elementsRange =
              range.endStart(elements.leftBracket, elements.rightBracket);
        } else {
          // TODO(brianwilkerson) Consider handling other iterables. Literal
          //  sets could be treated like lists, and arbitrary iterables by using
          //  a spread.
          return;
        }
      } else {
        // Invocation of an unhandled constructor.
        return;
      }
      //
      // Build the edit.
      //
      await builder.addDartFileEdit(file, (builder) {
        builder.addReplacement(range.node(creation), (builder) {
          if (constructorTypeArguments != null) {
            builder.write(utils.getNodeText(constructorTypeArguments));
          } else if (elementTypeArguments != null) {
            builder.write(utils.getNodeText(elementTypeArguments));
          } else if (!_setWouldBeInferred(creation)) {
            builder.write('<dynamic>');
          }
          builder.write('{');
          if (elementsRange != null) {
            builder.write(utils.getRangeText(elementsRange));
          }
          builder.write('}');
        });
      });
    }
  }

  /// Return the invocation of `List.toSet` that is to be converted, or `null`
  /// if the cursor is not inside a invocation of `List.toSet`.
  MethodInvocation? _findInvocationOfToSet() {
    var invocation = node.thisOrAncestorOfType<MethodInvocation>();
    if (invocation == null ||
        node.offset > invocation.argumentList.offset ||
        invocation.methodName.name != 'toSet' ||
        invocation.target is! ListLiteral) {
      return null;
    }
    return invocation;
  }

  /// Return the invocation of a `Set` constructor that is to be converted, or
  /// `null` if the cursor is not inside the invocation of a constructor.
  InstanceCreationExpression? _findSetCreation() {
    var creation = node.thisOrAncestorOfType<InstanceCreationExpression>();
    if (creation == null) {
      return null;
    }

    if (node.offset > creation.argumentList.offset) {
      return null;
    }

    var type = creation.staticType;
    if (type is! InterfaceType) {
      return null;
    }

    // TODO(brianwilkerson) Consider also accepting uses of LinkedHashSet.
    if (type.element != typeProvider.setElement) {
      return null;
    }
    return creation;
  }

  /// Return `true` if the instance [creation] contains at least one unambiguous
  /// element that would cause a set to be inferred.
  bool _hasUnambiguousElement(InstanceCreationExpression creation) {
    var arguments = creation.argumentList.arguments;
    if (arguments.isEmpty) {
      return false;
    }
    return _listHasUnambiguousElement(arguments[0]);
  }

  /// Return `true` if the [element] is sufficient to lexically make the
  /// enclosing literal a set literal rather than a map.
  bool _isUnambiguousElement(CollectionElement? element) {
    if (element is ForElement) {
      return _isUnambiguousElement(element.body);
    } else if (element is IfElement) {
      return _isUnambiguousElement(element.thenElement) ||
          _isUnambiguousElement(element.elseElement);
    } else if (element is Expression) {
      return true;
    }
    return false;
  }

  /// Return `true` if the given [node] is a list literal whose elements, if
  /// placed inside curly braces, would lexically make the resulting literal a
  /// set literal rather than a map literal.
  bool _listHasUnambiguousElement(AstNode node) {
    if (node is ListLiteral && node.elements.isNotEmpty) {
      for (var element in node.elements) {
        if (_isUnambiguousElement(element)) {
          return true;
        }
      }
    }
    return false;
  }

  /// Return `true` if a set would be inferred if the literal replacing the
  /// instance [creation] did not have explicit type arguments.
  bool _setWouldBeInferred(InstanceCreationExpression creation) {
    var parent = creation.parent!;
    if (parent is VariableDeclaration) {
      var parent2 = parent.parent;
      if (parent2 is VariableDeclarationList &&
          parent2.type?.type?.element == typeProvider.setElement) {
        return true;
      }
    } else if (parent.parent is InvocationExpression) {
      var parameterElement = creation.staticParameterElement;
      if (parameterElement?.type.element == typeProvider.setElement) {
        return true;
      }
    }
    return _hasUnambiguousElement(creation);
  }

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