// 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
  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();
}
