// 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/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
  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>();
    // TODO(brianwilkerson) Consider also accepting uses of LinkedHashSet.
    if (creation == null ||
        node.offset > creation.argumentList.offset ||
        creation.staticType.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 == null || 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;
      }
    }
    return _hasUnambiguousElement(creation);
  }

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