// Copyright (c) 2019, 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/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/element/member.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/type_system.dart';

class ExtensionMemberResolver {
  final ResolverVisitor _resolver;

  ExtensionMemberResolver(this._resolver);

  DartType get _dynamicType => _typeProvider.dynamicType;

  ErrorReporter get _errorReporter => _resolver.errorReporter;

  Scope get _nameScope => _resolver.nameScope;

  TypeProvider get _typeProvider => _resolver.typeProvider;

  TypeSystem get _typeSystem => _resolver.typeSystem;

  /// Return the most specific extension in the current scope for this [type],
  /// that defines the member with the the [name] and [kind].
  ///
  /// If no applicable extensions, return `null`.
  ///
  /// If the match is ambiguous, report an error and return `null`.
  ResolutionResult findExtension(
      DartType type, String name, Expression target, ElementKind kind) {
    var extensions = _getApplicable(type, name, kind);

    if (extensions.isEmpty) {
      return ResolutionResult.none;
    }

    if (extensions.length == 1) {
      return ResolutionResult(extensions[0].instantiatedMember);
    }

    var extension = _chooseMostSpecific(extensions);
    if (extension != null) {
      return ResolutionResult(extension.instantiatedMember);
    }

    _errorReporter.reportErrorForNode(
      CompileTimeErrorCode.AMBIGUOUS_EXTENSION_METHOD_ACCESS,
      target,
      [
        name,
        extensions[0].element.name,
        extensions[1].element.name,
      ],
    );
    return ResolutionResult.ambiguous;
  }

  /// Return the member with the [name] (without `=`) of the given [kind].
  ///
  /// The [node] is fully resolved, and its type arguments are set.
  ExecutableElement getOverrideMember(
      ExtensionOverride node, String name, ElementKind kind) {
    ExtensionElement element = node.extensionName.staticElement;

    ExecutableElement member;
    if (kind == ElementKind.GETTER) {
      member = element.getGetter(name);
    } else if (kind == ElementKind.METHOD) {
      member = element.getMethod(name);
    } else if (kind == ElementKind.SETTER) {
      member = element.getSetter(name);
    }
    if (member == null) return null;

    return ExecutableMember.from2(
      member,
      Substitution.fromPairs(
        element.typeParameters,
        node.typeArgumentTypes,
      ),
    );
  }

  /// Perform upward inference for the override.
  void resolveOverride(ExtensionOverride node) {
    var nodeImpl = node as ExtensionOverrideImpl;
    var element = node.staticElement;
    var typeParameters = element.typeParameters;

    if (!_isValidContext(node)) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.EXTENSION_OVERRIDE_WITHOUT_ACCESS,
        node,
      );
      nodeImpl.staticType = _dynamicType;
    }

    var arguments = node.argumentList.arguments;
    if (arguments.length != 1) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT,
        node.argumentList,
      );
      nodeImpl.typeArgumentTypes = _listOfDynamic(typeParameters);
      nodeImpl.extendedType = _dynamicType;
      return;
    }

    var receiverExpression = arguments[0];
    var receiverType = receiverExpression.staticType;

    var typeArgumentTypes = _inferTypeArguments(node, receiverType);
    nodeImpl.typeArgumentTypes = typeArgumentTypes;

    var substitution = Substitution.fromPairs(
      typeParameters,
      typeArgumentTypes,
    );

    nodeImpl.extendedType = substitution.substituteType(element.extendedType);

    _checkTypeArgumentsMatchingBounds(
      typeParameters,
      node.typeArguments,
      typeArgumentTypes,
      substitution,
    );

    if (!_typeSystem.isAssignableTo(receiverType, node.extendedType)) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE,
        receiverExpression,
        [receiverType, node.extendedType],
      );
    }
  }

  /// Set the type context for the receiver of the override.
  ///
  /// The context of the invocation that is made through the override does
  /// not affect the type inference of the override and the receiver.
  void setOverrideReceiverContextType(ExtensionOverride node) {
    var element = node.staticElement;
    var typeParameters = element.typeParameters;

    var arguments = node.argumentList.arguments;
    if (arguments.length != 1) {
      return;
    }

    List<DartType> typeArgumentTypes;
    var typeArguments = node.typeArguments;
    if (typeArguments != null) {
      var arguments = typeArguments.arguments;
      if (arguments.length == typeParameters.length) {
        typeArgumentTypes = arguments.map((a) => a.type).toList();
      } else {
        typeArgumentTypes = _listOfDynamic(typeParameters);
      }
    } else {
      typeArgumentTypes = List.filled(
        typeParameters.length,
        UnknownInferredType.instance,
      );
    }

    var extendedForDownward = Substitution.fromPairs(
      typeParameters,
      typeArgumentTypes,
    ).substituteType(element.extendedType);

    var receiver = arguments[0];
    InferenceContext.setType(receiver, extendedForDownward);
  }

  void _checkTypeArgumentsMatchingBounds(
    List<TypeParameterElement> typeParameters,
    TypeArgumentList typeArgumentList,
    List<DartType> typeArgumentTypes,
    Substitution substitution,
  ) {
    if (typeArgumentList != null) {
      for (var i = 0; i < typeArgumentTypes.length; i++) {
        var argType = typeArgumentTypes[i];
        var boundType = typeParameters[i].bound;
        if (boundType != null) {
          boundType = substitution.substituteType(boundType);
          if (!_typeSystem.isSubtypeOf(argType, boundType)) {
            _errorReporter.reportTypeErrorForNode(
              CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
              typeArgumentList.arguments[i],
              [argType, boundType],
            );
          }
        }
      }
    }
  }

  /// Return the most specific extension or `null` if no single one can be
  /// identified.
  _InstantiatedExtension _chooseMostSpecific(
      List<_InstantiatedExtension> extensions) {
    //
    // https://github.com/dart-lang/language/blob/master/accepted/future-releases/static-extension-methods/feature-specification.md#extension-conflict-resolution:
    //
    // If more than one extension applies to a specific member invocation, then
    // we resort to a heuristic to choose one of the extensions to apply. If
    // exactly one of them is "more specific" than all the others, that one is
    // chosen. Otherwise it is a compile-time error.
    //
    // An extension with on type clause T1 is more specific than another
    // extension with on type clause T2 iff
    //
    // 1. T2 is declared in a platform library, and T1 is not, or
    // 2. they are both declared in platform libraries or both declared in
    //    non-platform libraries, and
    // 3. the instantiated type (the type after applying type inference from the
    //    receiver) of T1 is a subtype of the instantiated type of T2 and either
    //    not vice versa, or
    // 4. the instantiate-to-bounds type of T1 is a subtype of the
    //    instantiate-to-bounds type of T2 and not vice versa.
    //

    for (var i = 0; i < extensions.length; i++) {
      var e1 = extensions[i];
      var isMoreSpecific = true;
      for (var j = 0; j < extensions.length; j++) {
        var e2 = extensions[j];
        if (i != j && !_isMoreSpecific(e1, e2)) {
          isMoreSpecific = false;
          break;
        }
      }
      if (isMoreSpecific) {
        return e1;
      }
    }

    // Otherwise fail.
    return null;
  }

  /// Return extensions for the [type] that match the given [name] in the
  /// current scope.
  List<_InstantiatedExtension> _getApplicable(
      DartType type, String name, ElementKind kind) {
    var candidates = _getExtensionsWithMember(name, kind);

    var instantiatedExtensions = <_InstantiatedExtension>[];
    for (var candidate in candidates) {
      var typeParameters = candidate.extension.typeParameters;
      var inferrer = GenericInferrer(
        _typeProvider,
        _typeSystem,
        typeParameters,
      );
      inferrer.constrainArgument(
        type,
        candidate.extension.extendedType,
        'extendedType',
      );
      var typeArguments = inferrer.infer(typeParameters, failAtError: true);
      if (typeArguments == null) {
        continue;
      }

      var substitution = Substitution.fromPairs(
        typeParameters,
        typeArguments,
      );
      var extendedType = substitution.substituteType(
        candidate.extension.extendedType,
      );
      if (!_isSubtypeOf(type, extendedType)) {
        continue;
      }

      instantiatedExtensions.add(
        _InstantiatedExtension(
          candidate.extension,
          extendedType,
          ExecutableMember.from2(
            candidate.member,
            substitution,
          ),
        ),
      );
    }

    return instantiatedExtensions;
  }

  /// Return extensions from the current scope, that define a member with the
  /// given[name].
  List<_CandidateExtension> _getExtensionsWithMember(
    String name,
    ElementKind kind,
  ) {
    var candidates = <_CandidateExtension>[];

    /// Return `true` if the [elementName] matches the target [name], taking
    /// into account the `=` on the end of the names of setters.
    bool matchesName(String elementName) {
      if (elementName.endsWith('=') && !name.endsWith('=')) {
        elementName = elementName.substring(0, elementName.length - 1);
      }
      return elementName == name;
    }

    /// Add the given [extension] to the list of [candidates] if it defined a
    /// member whose name matches the target [name].
    void checkExtension(ExtensionElement extension) {
      if (kind == ElementKind.GETTER) {
        for (var accessor in extension.accessors) {
          if (accessor.isGetter && matchesName(accessor.name)) {
            candidates.add(_CandidateExtension(extension, accessor));
            return;
          }
        }
      } else if (kind == ElementKind.SETTER) {
        for (var accessor in extension.accessors) {
          if (accessor.isSetter && matchesName(accessor.name)) {
            candidates.add(_CandidateExtension(extension, accessor));
            return;
          }
        }
      } else if (kind == ElementKind.METHOD) {
        for (var method in extension.methods) {
          if (matchesName(method.name)) {
            candidates.add(_CandidateExtension(extension, method));
            return;
          }
        }
        // Check for a getter that matches a function type.
        for (var accessor in extension.accessors) {
          if (accessor.type is FunctionType &&
              accessor.isGetter &&
              matchesName(accessor.name)) {
            candidates.add(_CandidateExtension(extension, accessor));
            return;
          }
        }
      }
    }

    for (var extension in _nameScope.extensions) {
      checkExtension(extension);
    }
    return candidates;
  }

  /// Given the generic [element] element, either return types specified
  /// explicitly in [typeArguments], or infer type arguments from the given
  /// [receiverType].
  ///
  /// If the number of explicit type arguments is different than the number
  /// of extension's type parameters, or inference fails, return `dynamic`
  /// for all type parameters.
  List<DartType> _inferTypeArguments(
    ExtensionOverride node,
    DartType receiverType,
  ) {
    var element = node.staticElement;
    var typeParameters = element.typeParameters;
    if (typeParameters.isEmpty) {
      return const <DartType>[];
    }

    var typeArguments = node.typeArguments;
    if (typeArguments != null) {
      var arguments = typeArguments.arguments;
      if (arguments.length == typeParameters.length) {
        return arguments.map((a) => a.type).toList();
      } else {
        // TODO(scheglov) Report an error.
        return _listOfDynamic(typeParameters);
      }
    } else {
      var inferrer = GenericInferrer(
        _typeProvider,
        _typeSystem,
        typeParameters,
      );
      inferrer.constrainArgument(
        receiverType,
        element.extendedType,
        'extendedType',
      );
      return inferrer.infer(
        typeParameters,
        errorReporter: _errorReporter,
        errorNode: node.extensionName,
      );
    }
  }

  /// Instantiate the extended type of the [extension] to the bounds of the
  /// type formals of the extension.
  DartType _instantiateToBounds(ExtensionElement extension) {
    var typeParameters = extension.typeParameters;
    return Substitution.fromPairs(
      typeParameters,
      _typeSystem.instantiateTypeFormalsToBounds(typeParameters),
    ).substituteType(extension.extendedType);
  }

  bool _isMoreSpecific(_InstantiatedExtension e1, _InstantiatedExtension e2) {
    var t10 = e1.element.extendedType;
    var t20 = e2.element.extendedType;
    var t11 = e1._extendedType;
    var t21 = e2._extendedType;

    bool inSdk(DartType type) {
      if (type.isDynamic || type.isVoid) {
        return true;
      }
      return t20.element.library.isInSdk;
    }

    if (inSdk(t20)) {
      //  1. T2 is declared in a platform library, and T1 is not
      if (!inSdk(t10)) {
        return true;
      }
    } else if (inSdk(t10)) {
      return false;
    }

    // 2. they are both declared in platform libraries or both declared in
    //    non-platform libraries, and
    if (_isSubtypeAndNotViceVersa(t11, t21)) {
      // 3. the instantiated type (the type after applying type inference from
      //    the receiver) of T1 is a subtype of the instantiated type of T2 and
      //    either not vice versa
      return true;
    }

    // TODO(scheglov) store instantiated types
    var t12 = _instantiateToBounds(e1.element);
    var t22 = _instantiateToBounds(e2.element);
    if (_isSubtypeAndNotViceVersa(t12, t22)) {
      // or:
      // 4. the instantiate-to-bounds type of T1 is a subtype of the
      //    instantiate-to-bounds type of T2 and not vice versa.
      return true;
    }

    return false;
  }

  bool _isSubtypeAndNotViceVersa(DartType t1, DartType t2) {
    return _isSubtypeOf(t1, t2) && !_isSubtypeOf(t2, t1);
  }

  /// Ask the type system for a subtype check.
  bool _isSubtypeOf(DartType type1, DartType type2) =>
      _typeSystem.isSubtypeOf(type1, type2);

  List<DartType> _listOfDynamic(List<TypeParameterElement> parameters) {
    return List<DartType>.filled(parameters.length, _dynamicType);
  }

  /// Return `true` if the extension override [node] is being used as a target
  /// of an operation that might be accessing an instance member.
  static bool _isValidContext(ExtensionOverride node) {
    AstNode parent = node.parent;
    return parent is BinaryExpression && parent.leftOperand == node ||
        parent is FunctionExpressionInvocation && parent.function == node ||
        parent is IndexExpression && parent.target == node ||
        parent is MethodInvocation && parent.target == node ||
        parent is PrefixExpression ||
        parent is PropertyAccess && parent.target == node;
  }
}

class _CandidateExtension {
  final ExtensionElement extension;
  final ExecutableElement member;

  _CandidateExtension(this.extension, this.member);
}

class _InstantiatedExtension {
  final ExtensionElement element;
  final DartType _extendedType;
  final ExecutableElement instantiatedMember;

  _InstantiatedExtension(
    this.element,
    this._extendedType,
    this.instantiatedMember,
  );
}
