// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';

class AnnotationResolver {
  final ResolverVisitor _resolver;

  AnnotationResolver(this._resolver);

  LibraryElement get _definingLibrary => _resolver.definingLibrary;

  ErrorReporter get _errorReporter => _resolver.errorReporter;

  bool get _genericMetadataIsEnabled =>
      _definingLibrary.featureSet.isEnabled(Feature.generic_metadata);

  void resolve(AnnotationImpl node,
      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
    AstNode parent = node.parent;

    node.typeArguments?.accept(_resolver);
    _resolve(node, whyNotPromotedList);

    var elementAnnotationImpl =
        node.elementAnnotation as ElementAnnotationImpl?;
    if (elementAnnotationImpl == null) {
      // Analyzer ignores annotations on "part of" directives.
      assert(parent is PartDirective || parent is PartOfDirective);
    } else {
      elementAnnotationImpl.annotationAst = _createCloner().cloneNode(node);
    }
  }

  void _classConstructorInvocation(
    AnnotationImpl node,
    ClassElement classElement,
    SimpleIdentifierImpl? constructorName,
    ArgumentList argumentList,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    ConstructorElement? constructorElement;
    if (constructorName != null) {
      constructorElement = classElement.getNamedConstructor(
        constructorName.name,
      );
    } else {
      constructorElement = classElement.unnamedConstructor;
    }

    _constructorInvocation(
      node,
      constructorName,
      classElement.typeParameters,
      constructorElement,
      argumentList,
      (typeArguments) {
        return classElement.instantiate(
          typeArguments: typeArguments,
          nullabilitySuffix: _resolver.noneOrStarSuffix,
        );
      },
      whyNotPromotedList,
    );
  }

  void _classGetter(
    AnnotationImpl node,
    ClassElement classElement,
    SimpleIdentifierImpl? getterName,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    ExecutableElement? getter;
    if (getterName != null) {
      getter = classElement.getGetter(getterName.name);
      getter = _resolver.toLegacyElement(getter);
      // Recovery, try to find a constructor.
      getter ??= classElement.getNamedConstructor(getterName.name);
    } else {
      getter = classElement.unnamedConstructor;
    }

    getterName?.staticElement = getter;
    node.element = getter;

    if (getterName != null && getter is PropertyAccessorElement) {
      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
      _resolveAnnotationElementGetter(node, getter);
    } else if (getter is! ConstructorElement) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_ANNOTATION,
        node,
      );
    }

    _visitArguments(node, whyNotPromotedList);
  }

  void _constructorInvocation(
    AnnotationImpl node,
    SimpleIdentifierImpl? constructorName,
    List<TypeParameterElement> typeParameters,
    ConstructorElement? constructorElement,
    ArgumentList argumentList,
    InterfaceType Function(List<DartType> typeArguments) instantiateElement,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    constructorElement = _resolver.toLegacyElement(constructorElement);
    constructorName?.staticElement = constructorElement;
    node.element = constructorElement;

    if (constructorElement == null) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_ANNOTATION,
        node,
      );
      _resolver.visitArgumentList(argumentList,
          whyNotPromotedList: whyNotPromotedList);
      return;
    }

    // If no type parameters, the elements are correct.
    if (typeParameters.isEmpty) {
      _resolveConstructorInvocationArguments(node);
      InferenceContext.setType(argumentList, constructorElement.type);
      _resolver.visitArgumentList(argumentList,
          whyNotPromotedList: whyNotPromotedList);
      return;
    }

    void resolveWithFixedTypeArguments(
      List<DartType> typeArguments,
      ConstructorElement constructorElement,
    ) {
      var type = instantiateElement(typeArguments);
      constructorElement = ConstructorMember.from(constructorElement, type);
      constructorName?.staticElement = constructorElement;
      node.element = constructorElement;
      _resolveConstructorInvocationArguments(node);

      InferenceContext.setType(argumentList, constructorElement.type);
      _resolver.visitArgumentList(argumentList,
          whyNotPromotedList: whyNotPromotedList);
    }

    if (!_genericMetadataIsEnabled) {
      var typeArguments = List.filled(
        typeParameters.length,
        DynamicTypeImpl.instance,
      );
      resolveWithFixedTypeArguments(typeArguments, constructorElement);
      return;
    }

    var typeArgumentList = node.typeArguments;
    if (typeArgumentList != null) {
      List<DartType> typeArguments;
      if (typeArgumentList.arguments.length == typeParameters.length) {
        typeArguments = typeArgumentList.arguments
            .map((element) => element.typeOrThrow)
            .toList();
      } else {
        typeArguments = List.filled(
          typeParameters.length,
          DynamicTypeImpl.instance,
        );
      }
      resolveWithFixedTypeArguments(typeArguments, constructorElement);
      return;
    }

    _resolver.visitArgumentList(argumentList,
        whyNotPromotedList: whyNotPromotedList);

    var elementToInfer = ConstructorElementToInfer(
      typeParameters,
      constructorElement,
    );
    var constructorRawType = elementToInfer.asType;

    var inferred = _resolver.inferenceHelper.inferGenericInvoke(
        node, constructorRawType, typeArgumentList, argumentList, node,
        isConst: true)!;

    constructorElement = ConstructorMember.from(
      constructorElement,
      inferred.returnType as InterfaceType,
    );
    constructorName?.staticElement = constructorElement;
    node.element = constructorElement;
    _resolveConstructorInvocationArguments(node);
  }

  /// Return a newly created cloner that can be used to clone constant
  /// expressions.
  ///
  /// TODO(scheglov) this is duplicate
  ConstantAstCloner _createCloner() {
    return ConstantAstCloner();
  }

  void _extensionGetter(
    AnnotationImpl node,
    ExtensionElement extensionElement,
    SimpleIdentifierImpl? getterName,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    ExecutableElement? getter;
    if (getterName != null) {
      getter = extensionElement.getGetter(getterName.name);
      getter = _resolver.toLegacyElement(getter);
    }

    getterName?.staticElement = getter;
    node.element = getter;

    if (getterName != null && getter is PropertyAccessorElement) {
      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
      _resolveAnnotationElementGetter(node, getter);
    } else {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_ANNOTATION,
        node,
      );
    }

    _visitArguments(node, whyNotPromotedList);
  }

  void _propertyAccessorElement(
    AnnotationImpl node,
    SimpleIdentifierImpl name,
    PropertyAccessorElement element,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    element = _resolver.toLegacyElement(element);
    name.staticElement = element;
    node.element = element;

    _resolveAnnotationElementGetter(node, element);
    _visitArguments(node, whyNotPromotedList);
  }

  void _resolve(AnnotationImpl node,
      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
    SimpleIdentifierImpl name1;
    SimpleIdentifierImpl? name2;
    SimpleIdentifierImpl? name3;
    var nameNode = node.name;
    if (nameNode is PrefixedIdentifierImpl) {
      name1 = nameNode.prefix;
      name2 = nameNode.identifier;
      name3 = node.constructorName;
    } else {
      name1 = nameNode as SimpleIdentifierImpl;
      name2 = node.constructorName;
    }
    var argumentList = node.arguments;

    var element1 = _resolver.nameScope.lookup(name1.name).getter;
    name1.staticElement = element1;

    if (element1 == null) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.UNDEFINED_ANNOTATION,
        node,
        [name1.name],
      );
      _visitArguments(node, whyNotPromotedList);
      return;
    }

    // Class(args) or Class.CONST
    if (element1 is ClassElement) {
      if (argumentList != null) {
        _classConstructorInvocation(
            node, element1, name2, argumentList, whyNotPromotedList);
      } else {
        _classGetter(node, element1, name2, whyNotPromotedList);
      }
      return;
    }

    // Extension.CONST
    if (element1 is ExtensionElement) {
      _extensionGetter(node, element1, name2, whyNotPromotedList);
      return;
    }

    // prefix.*
    if (element1 is PrefixElement) {
      if (name2 != null) {
        var element2 = element1.scope.lookup(name2.name).getter;
        name2.staticElement = element2;
        // prefix.Class(args) or prefix.Class.CONST
        if (element2 is ClassElement) {
          if (argumentList != null) {
            _classConstructorInvocation(
                node, element2, name3, argumentList, whyNotPromotedList);
          } else {
            _classGetter(node, element2, name3, whyNotPromotedList);
          }
          return;
        }
        // prefix.Extension.CONST
        if (element2 is ExtensionElement) {
          _extensionGetter(node, element2, name3, whyNotPromotedList);
          return;
        }
        // prefix.CONST
        if (element2 is PropertyAccessorElement) {
          _propertyAccessorElement(node, name2, element2, whyNotPromotedList);
          return;
        }

        // prefix.TypeAlias(args) or prefix.TypeAlias.CONST
        if (element2 is TypeAliasElement) {
          var aliasedType = element2.aliasedType;
          var argumentList = node.arguments;
          if (aliasedType is InterfaceType && argumentList != null) {
            _typeAliasConstructorInvocation(node, element2, name3, aliasedType,
                argumentList, whyNotPromotedList);
          } else {
            _typeAliasGetter(node, element2, name3, whyNotPromotedList);
          }
          return;
        }
        // undefined
        if (element2 == null) {
          _errorReporter.reportErrorForNode(
            CompileTimeErrorCode.UNDEFINED_ANNOTATION,
            node,
            [name2.name],
          );
          _visitArguments(node, whyNotPromotedList);
          return;
        }
      }
    }

    // CONST
    if (element1 is PropertyAccessorElement) {
      _propertyAccessorElement(node, name1, element1, whyNotPromotedList);
      return;
    }

    // TypeAlias(args) or TypeAlias.CONST
    if (element1 is TypeAliasElement) {
      var aliasedType = element1.aliasedType;
      var argumentList = node.arguments;
      if (aliasedType is InterfaceType && argumentList != null) {
        _typeAliasConstructorInvocation(node, element1, name2, aliasedType,
            argumentList, whyNotPromotedList);
      } else {
        _typeAliasGetter(node, element1, name2, whyNotPromotedList);
      }
      return;
    }

    // TODO(scheglov) Must be const.
    if (element1 is VariableElement) {
      return;
    }

    _errorReporter.reportErrorForNode(
      CompileTimeErrorCode.INVALID_ANNOTATION,
      node,
    );

    _visitArguments(node, whyNotPromotedList);
  }

  void _resolveAnnotationElementGetter(
      Annotation annotation, PropertyAccessorElement accessorElement) {
    // The accessor should be synthetic, the variable should be constant, and
    // there should be no arguments.
    VariableElement variableElement = accessorElement.variable;
    if (!accessorElement.isSynthetic ||
        !variableElement.isConst ||
        annotation.arguments != null) {
      _errorReporter.reportErrorForNode(
          CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
    }
  }

  /// Given an [argumentList] and the [executableElement] that will be invoked
  /// using those argument, compute the list of parameters that correspond to
  /// the list of arguments. An error will be reported if any of the arguments
  /// cannot be matched to a parameter. Return the parameters that correspond to
  /// the arguments, or `null` if no correspondence could be computed.
  ///
  /// TODO(scheglov) this is duplicate
  List<ParameterElement?>? _resolveArgumentsToFunction(
      ArgumentList argumentList, ExecutableElement? executableElement) {
    if (executableElement == null) {
      return null;
    }
    List<ParameterElement> parameters = executableElement.parameters;
    return _resolveArgumentsToParameters(argumentList, parameters);
  }

  /// Given an [argumentList] and the [parameters] related to the element that
  /// will be invoked using those arguments, compute the list of parameters that
  /// correspond to the list of arguments. An error will be reported if any of
  /// the arguments cannot be matched to a parameter. Return the parameters that
  /// correspond to the arguments.
  ///
  /// TODO(scheglov) this is duplicate
  List<ParameterElement?> _resolveArgumentsToParameters(
      ArgumentList argumentList, List<ParameterElement> parameters) {
    return ResolverVisitor.resolveArgumentsToParameters(
        argumentList, parameters, _errorReporter.reportErrorForNode);
  }

  void _resolveConstructorInvocationArguments(AnnotationImpl node) {
    var argumentList = node.arguments;
    // error will be reported in ConstantVerifier
    if (argumentList == null) {
      return;
    }
    // resolve arguments to parameters
    var constructor = node.element;
    if (constructor is ConstructorElement) {
      var parameters = _resolveArgumentsToFunction(argumentList, constructor);
      if (parameters != null) {
        argumentList.correspondingStaticParameters = parameters;
      }
    }
  }

  void _typeAliasConstructorInvocation(
    AnnotationImpl node,
    TypeAliasElement typeAliasElement,
    SimpleIdentifierImpl? constructorName,
    InterfaceType aliasedType,
    ArgumentList argumentList,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    var constructorElement = aliasedType.lookUpConstructor(
      constructorName?.name,
      _definingLibrary,
    );

    _constructorInvocation(
      node,
      constructorName,
      typeAliasElement.typeParameters,
      constructorElement,
      argumentList,
      (typeArguments) {
        return typeAliasElement.instantiate(
          typeArguments: typeArguments,
          nullabilitySuffix: _resolver.noneOrStarSuffix,
        ) as InterfaceType;
      },
      whyNotPromotedList,
    );
  }

  void _typeAliasGetter(
    AnnotationImpl node,
    TypeAliasElement typeAliasElement,
    SimpleIdentifierImpl? getterName,
    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
  ) {
    ExecutableElement? getter;
    var aliasedType = typeAliasElement.aliasedType;
    if (aliasedType is InterfaceType) {
      var classElement = aliasedType.element;
      if (getterName != null) {
        getter = classElement.getGetter(getterName.name);
        getter = _resolver.toLegacyElement(getter);
      }
    }

    getterName?.staticElement = getter;
    node.element = getter;

    if (getterName != null && getter is PropertyAccessorElement) {
      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
      _resolveAnnotationElementGetter(node, getter);
    } else if (getter is! ConstructorElement) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_ANNOTATION,
        node,
      );
    }

    _visitArguments(node, whyNotPromotedList);
  }

  void _visitArguments(AnnotationImpl node,
      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
    var arguments = node.arguments;
    if (arguments != null) {
      _resolver.visitArgumentList(arguments,
          whyNotPromotedList: whyNotPromotedList);
    }
  }
}
