// 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 "core_patch.dart";

// NOTE: When making changes to this class, please also update
// `VmTarget.instantiateInvocation` and `VmTarget._invocationType` in
// `pkg/kernel/lib/target/vm.dart`.
class _InvocationMirror implements Invocation {
  // Constants describing the invocation kind.
  // _FIELD cannot be generated by regular invocation mirrors.
  static const int _UNINITIALIZED = -1;
  static const int _METHOD = 0;
  static const int _GETTER = 1;
  static const int _SETTER = 2;
  static const int _FIELD = 3;
  static const int _LOCAL_VAR = 4;
  static const int _KIND_SHIFT = 0;
  static const int _KIND_BITS = 3;
  static const int _KIND_MASK = (1 << _KIND_BITS) - 1;

  // These values, except _DYNAMIC and _SUPER, are only used when throwing
  // NoSuchMethodError for compile-time resolution failures.
  static const int _DYNAMIC = 0;
  static const int _SUPER = 1;
  static const int _STATIC = 2;
  static const int _CONSTRUCTOR = 3;
  static const int _TOP_LEVEL = 4;
  static const int _LEVEL_SHIFT = _KIND_BITS;
  static const int _LEVEL_BITS = 3;
  static const int _LEVEL_MASK = (1 << _LEVEL_BITS) - 1;

  // ArgumentsDescriptor layout. Keep in sync with enum in dart_entry.h.
  static const int _TYPE_ARGS_LEN = 0;
  static const int _COUNT = 1;
  static const int _SIZE = 2;
  static const int _POSITIONAL_COUNT = 3;
  static const int _FIRST_NAMED_ENTRY = 4;

  // Internal representation of the invocation mirror.
  String? _functionName;
  List<Object?>? _argumentsDescriptor;
  List<Object?>? _arguments;
  bool _isSuperInvocation = false;
  int _delayedTypeArgumentsLen = 0;

  // External representation of the invocation mirror; populated on demand.
  Symbol? _memberName;
  int _type = _UNINITIALIZED;
  List<Type>? _typeArguments;
  List<Object?>? _positionalArguments;
  Map<Symbol, Object?>? _namedArguments;

  _InvocationMirror._withType(this._memberName, int? type, this._typeArguments,
      this._positionalArguments, this._namedArguments)
      : _type = type ?? _UNINITIALIZED {
    _typeArguments ??= const <Type>[];
    _positionalArguments ??= const [];
    _namedArguments ??= const {};
  }

  void _setMemberNameAndType() {
    final funcName = _functionName!;
    if (_type == _UNINITIALIZED) {
      _type = 0;
    }
    if (funcName.startsWith("get:")) {
      _type |= _GETTER;
      _memberName = new internal.Symbol.unvalidated(funcName.substring(4));
    } else if (funcName.startsWith("set:")) {
      _type |= _SETTER;
      _memberName =
          new internal.Symbol.unvalidated(funcName.substring(4) + "=");
    } else {
      _type |=
          _isSuperInvocation ? (_SUPER << _LEVEL_SHIFT) | _METHOD : _METHOD;
      _memberName = new internal.Symbol.unvalidated(funcName);
    }
  }

  Symbol get memberName {
    if (_memberName == null) {
      _setMemberNameAndType();
    }
    return _memberName!;
  }

  int get _typeArgsLen {
    var typeArgsLen = _argumentsDescriptor![_TYPE_ARGS_LEN] as int;
    return typeArgsLen == 0 ? _delayedTypeArgumentsLen : typeArgsLen;
  }

  List<Type> get typeArguments {
    if (_typeArguments == null) {
      if (_typeArgsLen == 0) {
        return _typeArguments = const <Type>[];
      }
      // A TypeArguments object does not have a corresponding Dart class and
      // cannot be accessed as an array in Dart. Therefore, we need a native
      // call to unpack the individual types into a list.
      _typeArguments = _unpackTypeArguments(_arguments![0], _typeArgsLen);
    }
    return _typeArguments!;
  }

  // Unpack the given TypeArguments object into a new list of individual types.
  @pragma("vm:external-name", "InvocationMirror_unpackTypeArguments")
  external static List<Type> _unpackTypeArguments(
      typeArguments, int numTypeArguments);

  List get positionalArguments {
    if (_positionalArguments == null) {
      // The argument descriptor counts the receiver, but not the type arguments
      // as positional arguments.
      var numPositionalArguments =
          (_argumentsDescriptor![_POSITIONAL_COUNT] as int) - 1;
      if (numPositionalArguments == 0) {
        return _positionalArguments = const [];
      }
      // Exclude receiver and type args in the returned list.
      var receiverIndex = _typeArgsLen > 0 ? 1 : 0;
      var args = _arguments!;
      _positionalArguments = new _ImmutableList._from(
          args, receiverIndex + 1, numPositionalArguments);
    }
    return _positionalArguments!;
  }

  Map<Symbol, dynamic> get namedArguments {
    if (_namedArguments == null) {
      final argsDescriptor = _argumentsDescriptor!;
      var numArguments =
          (argsDescriptor[_COUNT] as int) - 1; // Exclude receiver.
      var numPositionalArguments =
          (argsDescriptor[_POSITIONAL_COUNT] as int) - 1;
      var numNamedArguments = numArguments - numPositionalArguments;
      if (numNamedArguments == 0) {
        return _namedArguments = const {};
      }
      var receiverIndex = _typeArgsLen > 0 ? 1 : 0;
      final namedArguments = new Map<Symbol, Object?>();
      for (var i = 0; i < numNamedArguments; i++) {
        var namedEntryIndex = _FIRST_NAMED_ENTRY + 2 * i;
        var pos = argsDescriptor[namedEntryIndex + 1] as int;
        var arg_name = argsDescriptor[namedEntryIndex] as String;
        var arg_value = _arguments![receiverIndex + pos];
        namedArguments[new internal.Symbol.unvalidated(arg_name)] = arg_value;
      }
      _namedArguments = new Map.unmodifiable(namedArguments);
    }
    return _namedArguments!;
  }

  bool get isMethod {
    if (_type == _UNINITIALIZED) {
      _setMemberNameAndType();
    }
    return (_type & _KIND_MASK) == _METHOD;
  }

  bool get isAccessor {
    if (_type == _UNINITIALIZED) {
      _setMemberNameAndType();
    }
    return (_type & _KIND_MASK) != _METHOD;
  }

  bool get isGetter {
    if (_type == _UNINITIALIZED) {
      _setMemberNameAndType();
    }
    return (_type & _KIND_MASK) == _GETTER;
  }

  bool get isSetter {
    if (_type == _UNINITIALIZED) {
      _setMemberNameAndType();
    }
    return (_type & _KIND_MASK) == _SETTER;
  }

  _InvocationMirror(this._functionName, this._argumentsDescriptor,
      this._arguments, this._isSuperInvocation, this._type,
      [this._delayedTypeArgumentsLen = 0]);

  _InvocationMirror._withoutType(this._functionName, this._typeArguments,
      this._positionalArguments, this._namedArguments, this._isSuperInvocation,
      [this._delayedTypeArgumentsLen = 0]);

  @pragma("vm:entry-point", "call")
  static _allocateInvocationMirror(String functionName,
      List argumentsDescriptor, List arguments, bool isSuperInvocation,
      [int type = _UNINITIALIZED]) {
    return new _InvocationMirror(
        functionName, argumentsDescriptor, arguments, isSuperInvocation, type);
  }

  // This factory is used when creating an `Invocation` for a closure call which
  // may have delayed type arguments. In that case, the arguments descriptor will
  // indicate 0 type arguments, but the actual number of type arguments are
  // passed in `delayedTypeArgumentsLen`. If any type arguments are available,
  // the type arguments vector will be the first entry in `arguments`.
  @pragma("vm:entry-point", "call")
  static _allocateInvocationMirrorForClosure(
      String functionName,
      List argumentsDescriptor,
      List arguments,
      int? type,
      int delayedTypeArgumentsLen) {
    return new _InvocationMirror(functionName, argumentsDescriptor, arguments,
        false, type ?? _UNINITIALIZED, delayedTypeArgumentsLen);
  }
}
