// Copyright (c) 2022, 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/member.dart'; // ignore: implementation_imports
import 'package:collection/collection.dart';

import 'analyzer.dart';
import 'util/dart_type_utilities.dart';

class EnumLikeClassDescription {
  final Map<DartObject, Set<FieldElement>> _enumConstants;
  EnumLikeClassDescription(this._enumConstants);

  /// Returns a fresh map of the class's enum-like constant values.
  Map<DartObject, Set<FieldElement>> get enumConstants => {..._enumConstants};
}

extension AstNodeNullableExtension on AstNode? {
  bool get isFieldNameShortcut {
    var node = this;
    if (node is NullCheckPattern) node = node.parent;
    if (node is NullAssertPattern) node = node.parent;
    return node is PatternField && node.name != null && node.name?.name == null;
  }
}

extension AstNodeExtension on AstNode {
  Iterable<AstNode> get childNodes => childEntities.whereType<AstNode>();

  /// Builds the list resulting from traversing the node in DFS and does not
  /// include the node itself.
  ///
  /// It excludes the nodes for which the [excludeCriteria] returns true. If
  /// [excludeCriteria] is not provided, all nodes are included.
  @Deprecated(
      'This approach is slow and slated for removal. Traversal via a standard visitor is preferred.')
  Iterable<AstNode> traverseNodesInDFS({AstNodePredicate? excludeCriteria}) {
    var nodes = <AstNode>{};
    var nodesToVisit = List.of(childNodes);
    if (excludeCriteria == null) {
      while (nodesToVisit.isNotEmpty) {
        var node = nodesToVisit.removeAt(0);
        nodes.add(node);
        nodesToVisit.insertAll(0, node.childNodes);
      }
    } else {
      while (nodesToVisit.isNotEmpty) {
        var node = nodesToVisit.removeAt(0);
        if (excludeCriteria(node)) continue;
        nodes.add(node);
        nodesToVisit.insertAll(0, node.childNodes);
      }
    }

    return nodes;
  }
}

extension BlockExtension on Block {
  /// Returns the last statement of this block, or `null` if this is empty.
  ///
  /// If the last immediate statement of this block is a [Block], recurses into
  /// it to find the last statement.
  Statement? get lastStatement {
    if (statements.isEmpty) {
      return null;
    }
    var lastStatement = statements.last;
    if (lastStatement is Block) {
      return lastStatement.lastStatement;
    }
    return lastStatement;
  }
}

extension ClassElementExtension on ClassElement {
  /// Returns an [EnumLikeClassDescription] for this if the latter is a valid
  /// "enum-like" class.
  ///
  /// An enum-like class must meet the following requirements:
  ///
  /// * is concrete,
  /// * has no public constructors,
  /// * has no factory constructors,
  /// * has two or more static const fields with the same type as the class,
  /// * has no subclasses declared in the defining library.
  ///
  /// The returned [EnumLikeClassDescription]'s `enumConstantNames` contains all
  /// of the static const fields with the same type as the class, with one
  /// exception; any static const field which is marked `@Deprecated` and is
  /// equal to another static const field with the same type as the class is not
  /// included. Such a field is assumed to be deprecated in favor of the field
  /// with equal value.
  EnumLikeClassDescription? get asEnumLikeClass {
    // See discussion: https://github.com/dart-lang/linter/issues/2083.

    // Must be concrete.
    if (isAbstract) {
      return null;
    }

    // With only private non-factory constructors.
    for (var constructor in constructors) {
      if (!constructor.isPrivate || constructor.isFactory) {
        return null;
      }
    }

    var type = thisType;

    // And 2 or more static const fields whose type is the enclosing class.
    var enumConstantCount = 0;
    var enumConstants = <DartObject, Set<FieldElement>>{};
    for (var field in fields) {
      // Ensure static const.
      if (field.isSynthetic || !field.isConst || !field.isStatic) {
        continue;
      }
      // Check for type equality.
      if (field.type != type) {
        continue;
      }
      var fieldValue = field.computeConstantValue();
      if (fieldValue == null) {
        continue;
      }
      enumConstantCount++;
      enumConstants.putIfAbsent(fieldValue, () => {}).add(field);
    }
    if (enumConstantCount < 2) {
      return null;
    }

    // And no subclasses in the defining library.
    if (hasSubclassInDefiningCompilationUnit) return null;

    return EnumLikeClassDescription(enumConstants);
  }

  bool get hasSubclassInDefiningCompilationUnit {
    var compilationUnit = library.definingCompilationUnit;
    for (var cls in compilationUnit.classes) {
      InterfaceType? classType = cls.thisType;
      do {
        classType = classType?.superclass;
        if (classType == thisType) {
          return true;
        }
      } while (classType != null && !classType.isDartCoreObject);
    }
    return false;
  }

  bool get isEnumLikeClass => asEnumLikeClass != null;

  /// Returns whether this class is exactly [otherName] declared in
  /// [otherLibrary].
  bool isClass(String otherName, String otherLibrary) =>
      name == otherName && library.name == otherLibrary;
}

extension ClassMemberListExtension on List<ClassMember> {
  MethodDeclaration? getMethod(String name) => whereType<MethodDeclaration>()
      .firstWhereOrNull((node) => node.name.lexeme == name);
}

extension ConstructorElementExtension on ConstructorElement {
  /// Returns whether `this` is the same element as the [className] constructor
  /// named [constructorName] declared in [uri].
  bool isSameAs({
    required String uri,
    required String className,
    required String constructorName,
  }) =>
      library.name == uri &&
      enclosingElement.name == className &&
      name == constructorName;
}

extension DartTypeExtension on DartType? {
  bool extendsClass(String? className, String library) {
    var self = this;
    if (self is InterfaceType) {
      return _extendsClass(self, <InterfaceElement>{}, className, library);
    }
    return false;
  }

  bool implementsAnyInterface(Iterable<InterfaceTypeDefinition> definitions) {
    bool isAnyInterface(InterfaceType i) =>
        definitions.any((d) => i.isSameAs(d.name, d.library));

    var typeToCheck = this;
    if (typeToCheck is TypeParameterType) {
      typeToCheck = typeToCheck.typeForInterfaceCheck;
    }
    if (typeToCheck is InterfaceType) {
      return isAnyInterface(typeToCheck) ||
          !typeToCheck.element.isSynthetic &&
              typeToCheck.element.allSupertypes.any(isAnyInterface);
    } else {
      return false;
    }
  }

  bool implementsInterface(String interface, String library) {
    var self = this;
    if (self is! InterfaceType) {
      return false;
    }
    bool predicate(InterfaceType i) => i.isSameAs(interface, library);
    var element = self.element;
    return predicate(self) ||
        !element.isSynthetic && element.allSupertypes.any(predicate);
  }

  /// Returns whether `this` is the same element as [interface], declared in
  /// [library].
  bool isSameAs(String? interface, String? library) {
    var self = this;
    return self is InterfaceType &&
        self.element.name == interface &&
        self.element.library.name == library;
  }

  static bool _extendsClass(
          InterfaceType? type,
          Set<InterfaceElement> seenElements,
          String? className,
          String? library) =>
      type != null &&
      seenElements.add(type.element) &&
      (type.isSameAs(className, library) ||
          _extendsClass(type.superclass, seenElements, className, library));
}

extension ElementExtension on Element {
  Element get canonicalElement {
    var self = this;
    if (self is PropertyAccessorElement) {
      var variable = self.variable;
      if (variable is FieldMember) {
        // A field element defined in a parameterized type where the values of
        // the type parameters are known.
        //
        // This concept should be invisible when comparing FieldElements, but a
        // bug in the analyzer causes FieldElements to not evaluate as
        // equivalent to equivalent FieldMembers. See
        // https://github.com/dart-lang/sdk/issues/35343.
        return variable.declaration;
      } else {
        return variable;
      }
    } else {
      return self;
    }
  }
}

extension ExpressionExtension on Expression? {
  bool get isNullLiteral => this?.unParenthesized is NullLiteral;
}

extension InhertanceManager3Extension on InheritanceManager3 {
  /// Returns the class member that is overridden by [member], if there is one,
  /// as defined by [getInherited].
  ExecutableElement? overriddenMember(Element? member) {
    if (member == null) {
      return null;
    }

    var interfaceElement = member.thisOrAncestorOfType<InterfaceElement>();
    if (interfaceElement == null) {
      return null;
    }
    var name = member.name;
    if (name == null) {
      return null;
    }

    var libraryUri = interfaceElement.library.source.uri;
    return getInherited(interfaceElement.thisType, Name(libraryUri, name));
  }
}

extension InterfaceElementExtension on InterfaceElement {
  /// Returns whether this element is exactly [otherName] declared in
  /// [otherLibrary].
  bool isClass(String otherName, String otherLibrary) =>
      name == otherName && library.name == otherLibrary;
}

extension InterfaceTypeExtension on InterfaceType {
  /// Returns the collection of all interfaces that this type implements,
  /// including itself.
  Iterable<InterfaceType> get implementedInterfaces {
    void searchSupertypes(
        InterfaceType? type,
        Set<InterfaceElement> alreadyVisited,
        List<InterfaceType> interfaceTypes) {
      if (type == null || !alreadyVisited.add(type.element)) {
        return;
      }
      interfaceTypes.add(type);
      searchSupertypes(type.superclass, alreadyVisited, interfaceTypes);
      for (var interface in type.interfaces) {
        searchSupertypes(interface, alreadyVisited, interfaceTypes);
      }
      for (var mixin in type.mixins) {
        searchSupertypes(mixin, alreadyVisited, interfaceTypes);
      }
    }

    var interfaceTypes = <InterfaceType>[];
    searchSupertypes(this, {}, interfaceTypes);
    return interfaceTypes;
  }
}

extension MethodDeclarationExtension on MethodDeclaration {
  bool get hasInheritedMethod => lookUpInheritedMethod() != null;

  /// Returns whether this method is an override of a method in any supertype.
  bool get isOverride {
    var name = declaredElement?.name;
    if (name == null) {
      return false;
    }
    var parentElement = declaredElement?.enclosingElement;
    if (parentElement is! InterfaceElement) {
      return false;
    }
    var parentLibrary = parentElement.library;

    if (isGetter) {
      // Search supertypes for a getter of the same name.
      return parentElement.allSupertypes
          .any((t) => t.lookUpGetter2(name, parentLibrary) != null);
    } else if (isSetter) {
      // Search supertypes for a setter of the same name.
      return parentElement.allSupertypes
          .any((t) => t.lookUpSetter2(name, parentLibrary) != null);
    } else {
      // Search supertypes for a method of the same name.
      return parentElement.allSupertypes
          .any((t) => t.lookUpMethod2(name, parentLibrary) != null);
    }
  }

  PropertyAccessorElement? lookUpGetter() {
    var declaredElement = this.declaredElement;
    if (declaredElement == null) {
      return null;
    }
    var parent = declaredElement.enclosingElement;
    if (parent is InterfaceElement) {
      return parent.lookUpGetter(name.lexeme, declaredElement.library);
    }
    if (parent is ExtensionElement) {
      return parent.getGetter(name.lexeme);
    }
    return null;
  }

  PropertyAccessorElement? lookUpInheritedConcreteGetter() {
    var declaredElement = this.declaredElement;
    if (declaredElement == null) {
      return null;
    }
    var parent = declaredElement.enclosingElement;
    if (parent is InterfaceElement) {
      return parent.lookUpInheritedConcreteGetter(
          name.lexeme, declaredElement.library);
    }
    // Extensions don't inherit.
    return null;
  }

  MethodElement? lookUpInheritedConcreteMethod() {
    var declaredElement = this.declaredElement;
    if (declaredElement != null) {
      var parent = declaredElement.enclosingElement;
      if (parent is InterfaceElement) {
        return parent.lookUpInheritedConcreteMethod(
            name.lexeme, declaredElement.library);
      }
    }
    // Extensions don't inherit.
    return null;
  }

  PropertyAccessorElement? lookUpInheritedConcreteSetter() {
    var declaredElement = this.declaredElement;
    if (declaredElement != null) {
      var parent = declaredElement.enclosingElement;
      if (parent is InterfaceElement) {
        return parent.lookUpInheritedConcreteSetter(
            name.lexeme, declaredElement.library);
      }
    }
    // Extensions don't inherit.
    return null;
  }

  MethodElement? lookUpInheritedMethod() {
    var declaredElement = this.declaredElement;
    if (declaredElement != null) {
      var parent = declaredElement.enclosingElement;
      if (parent is InterfaceElement) {
        return parent.lookUpInheritedMethod(
            name.lexeme, declaredElement.library);
      }
    }
    return null;
  }
}

extension NullableAstNodeExtension on AstNode? {
  Element? get canonicalElement {
    var self = this;
    if (self is Expression) {
      var node = self.unParenthesized;
      if (node is Identifier) {
        return node.staticElement?.canonicalElement;
      } else if (node is PropertyAccess) {
        return node.propertyName.staticElement?.canonicalElement;
      }
    }
    return null;
  }
}

extension TokenExtension on Token? {
  bool get isFinal => this?.keyword == Keyword.FINAL;
}

extension TokenTypeExtension on TokenType {
  TokenType get inverted => switch (this) {
        TokenType.LT_EQ => TokenType.GT_EQ,
        TokenType.LT => TokenType.GT,
        TokenType.GT => TokenType.LT,
        TokenType.GT_EQ => TokenType.LT_EQ,
        _ => this
      };
}
