// Copyright (c) 2012, 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.

part of "dart:core";

/// Representation of the invocation of a member on an object.
///
/// This is the type of objects passed to [Object.noSuchMethod] when
/// an object doesn't support the member invocation that was attempted
/// on it.
abstract class Invocation {
  Invocation();

  /// Creates an invocation corresponding to a method invocation.
  ///
  /// The method invocation has no type arguments.
  /// If the named arguments are omitted, they default to no named arguments.
  @pragma("wasm:entry-point")
  factory Invocation.method(
    Symbol memberName,
    Iterable<Object?>? positionalArguments, [
    Map<Symbol, Object?>? namedArguments,
  ]) =>
      _Invocation.method(memberName, null, positionalArguments, namedArguments);

  /// Creates an invocation corresponding to a generic method invocation.
  ///
  /// If [typeArguments] is `null` or empty, the constructor is equivalent to
  /// calling [Invocation.method] with the remaining arguments.
  /// All the individual type arguments must be non-null.
  ///
  /// If the named arguments are omitted, they default to no named arguments.
  @pragma("wasm:entry-point")
  factory Invocation.genericMethod(
    Symbol memberName,
    Iterable<Type>? typeArguments,
    Iterable<Object?>? positionalArguments, [
    Map<Symbol, Object?>? namedArguments,
  ]) => _Invocation.method(
    memberName,
    typeArguments,
    positionalArguments,
    namedArguments,
  );

  /// Creates an invocation corresponding to a getter invocation.
  @pragma("wasm:entry-point")
  factory Invocation.getter(Symbol name) = _Invocation.getter;

  /// Creates an invocation corresponding to a setter invocation.
  ///
  /// This constructor accepts any [Symbol] as [memberName], but remember that
  /// *actual setter names* end in `=`, so the invocation corresponding
  /// to `object.member = value` is
  /// ```dart
  /// Invocation.setter(const Symbol("member="), value)
  /// ```
  @pragma("wasm:entry-point")
  factory Invocation.setter(Symbol memberName, Object? argument) =
      _Invocation.setter;

  /// The name of the invoked member.
  Symbol get memberName;

  /// An unmodifiable view of the type arguments of the call.
  ///
  /// If the member is a getter, setter or operator,
  /// the type argument list is always empty.
  List<Type> get typeArguments => const <Type>[];

  /// An unmodifiable view of the positional arguments of the call.
  ///
  /// If the member is a getter, the positional arguments list is
  /// always empty.
  List<dynamic> get positionalArguments;

  /// An unmodifiable view of the named arguments of the call.
  ///
  /// If the member is a getter, setter or operator,
  /// the named arguments map is always empty.
  Map<Symbol, dynamic> get namedArguments;

  /// Whether the invocation was a method call.
  bool get isMethod;

  /// Whether the invocation was a getter call.
  /// If so, all three types of arguments lists are empty.
  bool get isGetter;

  /// Whether the invocation was a setter call.
  ///
  /// If so, [positionalArguments] has exactly one positional
  /// argument, [namedArguments] is empty, and typeArguments is
  /// empty.
  bool get isSetter;

  /// Whether the invocation was a getter or a setter call.
  bool get isAccessor => isGetter || isSetter;
}

/// Implementation of [Invocation] used by its factory constructors.
class _Invocation implements Invocation {
  final Symbol memberName;
  final List<Type> typeArguments;
  // Positional arguments is `null` for getters only.
  final List<Object?>? _positional;
  // Named arguments is `null` for accessors only.
  final Map<Symbol, Object?>? _named;

  _Invocation.method(
    this.memberName,
    Iterable<Type>? types,
    Iterable<Object?>? positional,
    Map<Symbol, Object?>? named,
  ) : typeArguments = _ensureNonNullTypes(types),
      _positional = positional == null
          ? const <Object?>[]
          : List<Object?>.unmodifiable(positional),
      _named = (named == null || named.isEmpty)
          ? const <Symbol, Object?>{}
          : Map<Symbol, Object?>.unmodifiable(named);

  _Invocation.getter(this.memberName)
    : typeArguments = const <Type>[],
      _positional = null,
      _named = null;

  _Invocation.setter(this.memberName, Object? argument)
    : typeArguments = const <Type>[],
      _positional = List<Object?>.unmodifiable([argument]),
      _named = null;

  List<dynamic> get positionalArguments => _positional ?? const <Object>[];

  Map<Symbol, dynamic> get namedArguments => _named ?? const <Symbol, Object>{};

  bool get isMethod => _named != null;
  bool get isGetter => _positional == null;
  bool get isSetter => _positional != null && _named == null;
  bool get isAccessor => _named == null;

  /// Checks that the elements of [types] are not null.
  static List<Type> _ensureNonNullTypes(Iterable<Type>? types) {
    if (types == null) return const <Type>[];
    List<Type> typeArguments = List<Type>.unmodifiable(types);
    for (int i = 0; i < typeArguments.length; i++) {
      if (typeArguments[i] == null) {
        throw ArgumentError.value(
          types,
          "types",
          "Type arguments must be non-null, was null at index $i.",
        );
      }
    }
    return typeArguments;
  }
}
