// 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.type.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
        ],
      );
    } else if (container is ExtensionElement) {
      _addMatcher(
        components: [node.identifier.name, container.displayName],
        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;
  }
}
