// 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/fix/data_driven/element_descriptor.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart'
    show ClassElement, ExtensionElement, PrefixElement;
import 'package:analyzer/dart/element/type.dart';

/// An object that can be used to determine whether an element is appropriate
/// for a given reference.
class ElementMatcher {
  /// The URIs of the libraries that are imported in the library containing the
  /// reference.
  final List<Uri> importedUris;

  /// The components of the element being referenced. The components are ordered
  /// from the most local to the most global.
  final List<String> components;

  /// A list of the kinds of elements that are appropriate for some given
  /// location in the code An empty list represents all kinds rather than no
  /// kinds.
  final List<ElementKind> validKinds;

  /// Initialize a newly created matcher representing a reference to an element
  /// whose name matches the given [components] and element [kinds] in a library
  /// that imports the [importedUris].
  ElementMatcher(
      {required this.importedUris,
      required this.components,
      required List<ElementKind> kinds})
      : assert(components.isNotEmpty),
        validKinds = kinds;

  /// Return `true` if this matcher matches the given [element].
  bool matches(ElementDescriptor element) {
    //
    // Check that the components in the element's name match the node.
    //
    // This algorithm is probably too general given that there will currently
    // always be either one or two components.
    //
    var elementComponents = element.components;
    var elementComponentCount = elementComponents.length;
    var nodeComponentCount = components.length;
    if (nodeComponentCount == elementComponentCount) {
      // The component counts are the same, so we can just compare the two
      // lists.
      for (var i = 0; i < nodeComponentCount; i++) {
        if (elementComponents[i] != components[i]) {
          return false;
        }
      }
    } else if (nodeComponentCount < elementComponentCount) {
      // The node has fewer components, which can happen, for example, when we
      // can't figure out the class that used to define a field. We treat the
      // missing components as wildcards and match the rest.
      for (var i = 0; i < nodeComponentCount; i++) {
        if (elementComponents[i] != components[i]) {
          return false;
        }
      }
    } else {
      // The node has more components than the element, which can happen when a
      // constructor is implicitly renamed because the class was renamed.
      // TODO(brianwilkerson) Figure out whether we want to support this or
      //  whether we want to require fix data authors to explicitly include the
      //  change to the constructor. On the one hand it's more work for the
      //  author, on the other hand it give us more data so we're less likely to
      //  make apply a fix in invalid circumstances.
      if (elementComponents[0] != components[1]) {
        return false;
      }
    }
    //
    // Check whether the kind of element matches the possible kinds that the
    // node might have.
    //
    if (validKinds.isNotEmpty && !validKinds.contains(element.kind)) {
      return false;
    }
    //
    // Check whether the element is in an imported library.
    //
    var libraryUris = element.libraryUris;
    for (var importedUri in importedUris) {
      if (libraryUris.contains(importedUri)) {
        return true;
      }
    }
    return false;
  }

  /// Return a list of element matchers that will match the element that is, or
  /// should be, associated with the given [node]. The list will be empty if
  /// there are no appropriate matchers for the [node].
  static List<ElementMatcher> matchersForNode(AstNode? node) {
    if (node == null) {
      return const <ElementMatcher>[];
    }
    var importedUris = _importElementsForNode(node);
    if (importedUris == null) {
      return const <ElementMatcher>[];
    }
    var builder = _MatcherBuilder(importedUris);
    builder.buildMatchersForNode(node);
    return builder.matchers.toList();
  }

  /// Return the URIs of the imports in the library containing the [node], or
  /// `null` if the imports can't be determined.
  static List<Uri>? _importElementsForNode(AstNode node) {
    var root = node.root;
    if (root is! CompilationUnit) {
      return null;
    }
    var importedUris = <Uri>[];
    var library = root.declaredElement?.library;
    if (library == null) {
      return null;
    }
    for (var importElement in library.imports) {
      // TODO(brianwilkerson) Filter based on combinators to help avoid making
      //  invalid suggestions.
      var uri = importElement.importedLibrary?.source.uri;
      if (uri != null) {
        // The [uri] is `null` if the literal string is not a valid URI.
        importedUris.add(uri);
      }
    }
    return importedUris;
  }
}

/// A helper class used to build a list of element matchers.
class _MatcherBuilder {
  final List<ElementMatcher> matchers = [];

  final List<Uri> importedUris;

  _MatcherBuilder(this.importedUris);

  void buildMatchersForNode(AstNode? node) {
    if (node is ArgumentList) {
      _buildFromArgumentList(node);
    } else if (node is BinaryExpression) {
      _buildFromBinaryExpression(node);
    } else if (node is ConstructorName) {
      _buildFromConstructorName(node);
    } else if (node is Literal) {
      var parent = node.parent;
      if (parent is ArgumentList) {
        _buildFromArgumentList(parent);
      }
    } else if (node is NamedType) {
      _buildFromNamedType(node);
    } else if (node is PrefixedIdentifier) {
      _buildFromPrefixedIdentifier(node);
    } else if (node is SimpleIdentifier) {
      _buildFromSimpleIdentifier(node);
    } else if (node is TypeArgumentList) {
      _buildFromTypeArgumentList(node);
    }
  }

  void _addMatcher(
      {required List<String> components, required List<ElementKind> kinds}) {
    matchers.add(ElementMatcher(
        importedUris: importedUris, components: components, kinds: kinds));
  }

  /// Build a matcher for the element being invoked.
  void _buildFromArgumentList(ArgumentList node) {
    var parent = node.parent;
    if (parent is Annotation) {
      _addMatcher(
        components: [parent.constructorName?.name ?? '', parent.name.name],
        kinds: [ElementKind.constructorKind],
      );
      // } else if (parent is ExtensionOverride) {
      //   // TODO(brianwilkerson) Determine whether this branch can be reached.
      //   _buildFromExtensionOverride(parent);
    } else if (parent is FunctionExpressionInvocation) {
      _buildFromFunctionExpressionInvocation(parent);
    } else if (parent is InstanceCreationExpression) {
      _buildFromInstanceCreationExpression(parent);
    } else if (parent is MethodInvocation) {
      _buildFromMethodInvocation(parent);
    } else if (parent is RedirectingConstructorInvocation) {
      var grandparent = parent.parent;
      if (grandparent is ConstructorDeclaration) {
        _addMatcher(
          components: [
            parent.constructorName?.name ?? '',
            grandparent.returnType.name
          ],
          kinds: [ElementKind.constructorKind],
        );
      }
    } else if (parent is SuperConstructorInvocation) {
      var superclassName = parent.staticElement?.enclosingElement.name;
      if (superclassName != null) {
        _addMatcher(
          components: [parent.constructorName?.name ?? '', superclassName],
          kinds: [ElementKind.constructorKind],
        );
      }
    }
  }

  /// Build a matcher for the operator being invoked.
  void _buildFromBinaryExpression(BinaryExpression node) {
    // TODO(brianwilkerson) Implement this method in order to support changes to
    //  operators.
  }

  /// Build a matcher for the constructor being referenced.
  void _buildFromConstructorName(ConstructorName node) {
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    // TODO(brianwilkerson) Use 'new' for the name of the unnamed constructor.
    var constructorName = node.name?.name ?? ''; // ?? 'new';
    var className = node.type2.name.simpleName;
    _addMatcher(
      components: [constructorName, className],
      kinds: const [ElementKind.constructorKind],
    );
    _addMatcher(
      components: [className],
      kinds: const [ElementKind.classKind],
    );
  }

  /// Build a matcher for the extension.
  void _buildFromExtensionOverride(ExtensionOverride node) {
    _addMatcher(
      components: [node.extensionName.name],
      kinds: [ElementKind.extensionKind],
    );
  }

  /// Build a matcher for the function being invoked.
  void _buildFromFunctionExpressionInvocation(
      FunctionExpressionInvocation node) {
    // TODO(brianwilkerson) This case was missed in the original implementation
    //  and there are no tests for it at this point, but it ought to be supported.
  }

  /// Build a matcher for the constructor being invoked.
  void _buildFromInstanceCreationExpression(InstanceCreationExpression node) {
    _buildFromConstructorName(node.constructorName);
  }

  /// Build a matcher for the method being declared.
  void _buildFromMethodDeclaration(MethodDeclaration node) {
    _addMatcher(
      components: [node.name.name],
      kinds: [ElementKind.methodKind],
    );
  }

  /// Build a matcher for the method being invoked.
  void _buildFromMethodInvocation(MethodInvocation node) {
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    // var element = node.methodName.staticElement;
    // if (element != null) {
    //   return _buildFromElement(element);
    // }
    var methodName = node.methodName;
    var targetName = _nameOfTarget(node.realTarget);
    if (targetName != null) {
      // If there is a target, and we know the type of the target, then we know
      // that a method is being invoked.
      _addMatcher(
        components: [methodName.name, targetName],
        kinds: [
          ElementKind.constructorKind,
          ElementKind.methodKind,
        ],
      );
    } else if (node.realTarget != null) {
      // If there is a target, but we don't know the type of the target, then
      // the target type might be undefined and this might have been either a
      // method invocation, an invocation of a function returned by a getter, or
      // a constructor invocation prior to the type having been deleted.
      _addMatcher(
        components: _componentsFromIdentifier(methodName),
        kinds: [
          ElementKind.constructorKind,
          ElementKind.getterKind,
          ElementKind.methodKind,
        ],
      );
    } else {
      // If there is no target, then this might have been either a method
      // invocation, a function invocation (of either a function or a function
      // returned from a getter), a constructor invocation, or an extension
      // override. If it's a constructor, then the change might have been to the
      // class rather than an individual constructor.
      _addMatcher(
        components: _componentsFromIdentifier(methodName),
        kinds: [
          ElementKind.classKind,
          ElementKind.constructorKind,
          ElementKind.extensionKind,
          ElementKind.functionKind,
          ElementKind.getterKind,
          ElementKind.methodKind,
        ],
      );
    }
  }

  /// Build a matcher for the type.
  void _buildFromNamedType(NamedType node) {
    var parent = node.parent;
    if (parent is ConstructorName) {
      return _buildFromConstructorName(parent);
    }
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    _addMatcher(
      components: [node.name.simpleName],
      kinds: const [
        ElementKind.classKind,
        ElementKind.enumKind,
        ElementKind.mixinKind,
        ElementKind.typedefKind
      ],
    );
    // TODO(brianwilkerson) Determine whether we can ever get here as a result
    //  of having a removed unnamed constructor.
    // _addMatcher(
    //   components: ['', node.name.name],
    //   kinds: const [ElementKind.constructorKind],
    // );
  }

  /// Build a matcher for the element represented by the prefixed identifier.
  void _buildFromPrefixedIdentifier(PrefixedIdentifier node) {
    var parent = node.parent;
    if (parent is NamedType) {
      return _buildFromNamedType(parent);
    }
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    var prefix = node.prefix;
    if (prefix.staticElement is PrefixElement) {
      var parent = node.parent;
      if ((parent is NamedType && parent.parent is! ConstructorName) ||
          (parent is PropertyAccess && parent.target == node)) {
        _addMatcher(components: [
          node.identifier.name
        ], kinds: const [
          ElementKind.classKind,
          ElementKind.enumKind,
          ElementKind.extensionKind,
          ElementKind.mixinKind,
          ElementKind.typedefKind
        ]);
      }
      _addMatcher(components: [
        node.identifier.name
      ], kinds: const [
        // If the old class has been removed then this might have been a
        // constructor invocation.
        ElementKind.constructorKind,
        ElementKind.functionKind, // tear-off
        ElementKind.getterKind,
        ElementKind.setterKind,
        ElementKind.variableKind
      ]);
    }
    // It looks like we're accessing a member, so try to figure out the
    // name of the type defining the member.
    var targetType = node.prefix.staticType;
    if (targetType is InterfaceType) {
      _addMatcher(
        components: [node.identifier.name, targetType.element.name],
        kinds: const [
          ElementKind.constantKind,
          ElementKind.fieldKind,
          ElementKind.functionKind, // tear-off
          ElementKind.getterKind,
          ElementKind.methodKind, // tear-off
          ElementKind.setterKind
        ],
      );
    }
    // It looks like we're accessing a member, but we don't know what kind of
    // member, so we include all of the member kinds.
    var container = node.prefix.staticElement;
    if (container is ClassElement) {
      _addMatcher(
        components: [node.identifier.name, container.name],
        kinds: const [
          ElementKind.constantKind,
          ElementKind.fieldKind,
          ElementKind.functionKind, // tear-off
          ElementKind.getterKind,
          ElementKind.methodKind, // tear-off
          ElementKind.setterKind
        ],
      );
    }
  }

  /// Build a matcher for the property being accessed.
  void _buildFromPropertyAccess(PropertyAccess node) {
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    var propertyName = node.propertyName;
    var targetName = _nameOfTarget(node.realTarget);
    List<String> components;
    if (targetName != null) {
      components = [propertyName.name, targetName];
    } else {
      components = _componentsFromIdentifier(propertyName);
    }
    _addMatcher(
      components: components,
      kinds: const [
        ElementKind.constantKind,
        ElementKind.fieldKind,
        ElementKind.functionKind, // tear-off, prefixed
        ElementKind.getterKind,
        ElementKind.methodKind, // tear-off, prefixed
        ElementKind.setterKind
      ],
    );
  }

  /// Build a matcher for the element referenced by the identifier.
  void _buildFromSimpleIdentifier(SimpleIdentifier node) {
    // TODO(brianwilkerson) Use the static element, if there is one, in order to
    //  get a more exact matcher.
    var parent = node.parent;
    if (parent is Label && parent.parent is NamedExpression) {
      // The parent of the named expression is an argument list. Because we
      // don't represent parameters as elements, the element we need to match
      // against is the invocation containing those arguments.
      _buildFromArgumentList(parent.parent!.parent as ArgumentList);
    } else if (parent is NamedType) {
      _buildFromNamedType(parent);
    } else if (parent is MethodDeclaration && node == parent.name) {
      _buildFromMethodDeclaration(parent);
    } else if (parent is MethodInvocation &&
        node == parent.methodName &&
        !_isPrefix(parent.target)) {
      _buildFromMethodInvocation(parent);
    } else if (parent is PrefixedIdentifier && node == parent.identifier) {
      _buildFromPrefixedIdentifier(parent);
    } else if (parent is PropertyAccess &&
        node == parent.propertyName &&
        !_isPrefix(parent.target)) {
      _buildFromPropertyAccess(parent);
    } else {
      // TODO(brianwilkerson) See whether the list of kinds can be specified.
      _addMatcher(components: [node.name], kinds: []);
    }
  }

  /// Build a matcher for the element with which the type arguments are
  /// associated.
  void _buildFromTypeArgumentList(TypeArgumentList node) {
    var parent = node.parent;
    if (parent is ExtensionOverride) {
      _buildFromExtensionOverride(parent);
    } else if (parent is FunctionExpressionInvocation) {
      _buildFromFunctionExpressionInvocation(parent);
    } else if (parent is InstanceCreationExpression) {
      _buildFromInstanceCreationExpression(parent);
    } else if (parent is MethodInvocation) {
      _buildFromMethodInvocation(parent);
    }
  }

  /// Return the components associated with the [identifier] when there is no
  /// contextual information.
  static List<String> _componentsFromIdentifier(SimpleIdentifier identifier) {
    var element = identifier.staticElement;
    if (element == null) {
      var parent = identifier.parent;
      if (parent is AssignmentExpression && identifier == parent.leftHandSide) {
        element = parent.writeElement;
      }
    }
    if (element != null) {
      var enclosingElement = element.enclosingElement;
      if (enclosingElement is ClassElement) {
        return [identifier.name, enclosingElement.name];
      } else if (enclosingElement is ExtensionElement) {
        var name = enclosingElement.name;
        if (name != null) {
          return [identifier.name, name];
        }
      }
    }
    return [identifier.name];
  }

  /// Return `true` if the [node] is a prefix
  static bool _isPrefix(AstNode? node) {
    return node is SimpleIdentifier && node.staticElement is PrefixElement;
  }

  /// Return the name of the class associated with the given [target].
  static String? _nameOfTarget(Expression? target) {
    if (target is SimpleIdentifier) {
      var type = target.staticType;
      if (type != null) {
        if (type is InterfaceType) {
          return type.element.name;
        } else if (type.isDynamic) {
          // The name is likely to be undefined.
          return target.name;
        }
        return null;
      }
      return target.name;
    } else if (target != null) {
      var type = target.staticType;
      if (type is InterfaceType) {
        return type.element.name;
      }
      return null;
    }
    return null;
  }
}

extension on Identifier {
  String get simpleName {
    var identifier = this;
    if (identifier is PrefixedIdentifier) {
      // The prefix isn't part of the name of the class.
      return identifier.identifier.name;
    }
    return name;
  }
}
