// 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.

part of 'types.dart';

class _JObjectType extends JType<JObject> {
  const _JObjectType();

  @override
  String get signature => "Ljava/lang/Object;";
}

Pointer<T> _getID<T extends NativeType>(
    JniPointerResult Function(
            Pointer<Void> ptr, Pointer<Char> name, Pointer<Char> sig)
        f,
    Pointer<Void> ptr,
    String name,
    String sig) {
  final result = using(
      (arena) => f(ptr, name.toNativeChars(arena), sig.toNativeChars(arena)));
  if (result.exception != nullptr) {
    _accessors.throwException(result.exception);
  }
  return result.id.cast<T>();
}

int _getCallType(int? callType, int defaultType, Set<int> allowed) {
  if (callType == null) return defaultType;
  if (allowed.contains(callType)) return callType;
  throw InvalidCallTypeException(callType, allowed);
}

T _callOrGet<T>(int? callType, JniResult Function(int) function) {
  final int finalCallType;
  late T result;
  switch (T) {
    case bool:
      finalCallType = _getCallType(
          callType, JniCallType.booleanType, {JniCallType.booleanType});
      result = function(finalCallType).boolean as T;
      break;
    case int:
      finalCallType = _getCallType(callType, JniCallType.intType, {
        JniCallType.byteType,
        JniCallType.charType,
        JniCallType.shortType,
        JniCallType.intType,
        JniCallType.longType,
      });
      final jniResult = function(finalCallType);
      switch (finalCallType) {
        case JniCallType.byteType:
          result = jniResult.byte as T;
          break;
        case JniCallType.shortType:
          result = jniResult.short as T;
          break;
        case JniCallType.charType:
          result = jniResult.char as T;
          break;
        case JniCallType.intType:
          result = jniResult.integer as T;
          break;
        case JniCallType.longType:
          result = jniResult.long as T;
          break;
      }
      break;
    case double:
      finalCallType = _getCallType(callType, JniCallType.doubleType,
          {JniCallType.floatType, JniCallType.doubleType});
      final jniResult = function(finalCallType);
      switch (finalCallType) {
        case JniCallType.floatType:
          result = jniResult.float as T;
          break;
        case JniCallType.doubleType:
          result = jniResult.doubleFloat as T;
          break;
      }
      break;
    case String:
    case JObject:
    case JString:
      finalCallType = _getCallType(
          callType, JniCallType.objectType, {JniCallType.objectType});
      final ref = function(finalCallType).object;
      final ctor = T == String
          ? (ref) => _env.asDartString(ref, deleteOriginal: true)
          : (T == JObject ? JObject.fromRef : JString.fromRef);
      result = ctor(ref) as T;
      break;
    case _VoidType:
      finalCallType =
          _getCallType(callType, JniCallType.voidType, {JniCallType.voidType});
      function(finalCallType).check();
      result = null as T;
      break;
    case dynamic:
      throw UnsupportedError("Return type not specified for JNI call");
    default:
      throw UnsupportedError('Unknown type $T');
  }
  return result;
}

T _callMethod<T>(int? callType, List<dynamic> args,
        JniResult Function(int, Pointer<JValue>) f) =>
    using((arena) {
      final jArgs = JValueArgs(args, arena);
      arena.onReleaseAll(jArgs.dispose);
      return _callOrGet<T>(callType, (ct) => f(ct, jArgs.values));
    });

T _getField<T>(int? callType, JniResult Function(int) f) {
  final result = _callOrGet<T>(callType, f);
  return result;
}

/// A high-level wrapper for JNI global object reference.
///
/// This is the base class for classes generated by `jnigen`.
class JObject extends JReference {
  /// The type which includes information such as the signature of this class.
  static const JType<JObject> type = _JObjectType();

  /// Construct a new [JObject] with [reference] as its underlying reference.
  JObject.fromRef(JObjectPtr reference) : super.fromRef(reference);

  JniClass? _jniClass;

  JniClass get _class {
    return _jniClass ??= getClass();
  }

  /// Deletes the JNI reference and marks this object as deleted. Any further
  /// uses will throw [UseAfterFreeException].
  @override
  void delete() {
    _jniClass?.delete();
    super.delete();
  }

  // TODO(#55): Support casting JObject subclasses

  /// Returns [JniClass] corresponding to concrete class of this object.
  ///
  /// This may be a subclass of compile-time class.
  JniClass getClass() {
    _ensureNotDeleted();
    final classRef = _env.GetObjectClass(reference);
    if (classRef == nullptr) {
      _accessors.throwException(_env.ExceptionOccurred());
    }
    return JniClass.fromRef(classRef);
  }

  /// Get [JFieldIDPtr] of instance field identified by [fieldName] & [signature].
  JFieldIDPtr getFieldID(String fieldName, String signature) {
    _ensureNotDeleted();
    return _getID(
        _accessors.getFieldID, _class.reference, fieldName, signature);
  }

  /// Get [JFieldIDPtr] of static field identified by [fieldName] & [signature].
  JFieldIDPtr getStaticFieldID(String fieldName, String signature) {
    _ensureNotDeleted();
    return _getID<jfieldID_>(
        _accessors.getStaticFieldID, _class.reference, fieldName, signature);
  }

  /// Get [JMethodIDPtr] of instance method [methodName] with [signature].
  JMethodIDPtr getMethodID(String methodName, String signature) {
    _ensureNotDeleted();
    return _getID<jmethodID_>(
        _accessors.getMethodID, _class.reference, methodName, signature);
  }

  /// Get [JMethodIDPtr] of static method [methodName] with [signature].
  JMethodIDPtr getStaticMethodID(String methodName, String signature) {
    _ensureNotDeleted();
    return _getID<jmethodID_>(
        _accessors.getStaticMethodID, _class.reference, methodName, signature);
  }

  /// Retrieve the value of the field using [fieldID].
  ///
  /// [callType] determines the return type of the underlying JNI call made.
  /// If the Java field is of `long` type, this must be [JniCallType.longType] and
  /// so on. Default is chosen based on return type [T], which maps int -> int,
  /// double -> double, void -> void, and JObject types to `Object`.
  ///
  /// If [T] is String or [JObject], required conversions are performed and
  /// final value is returned.
  T getField<T>(JFieldIDPtr fieldID, [int? callType]) {
    _ensureNotDeleted();
    if (callType == JniCallType.voidType) {
      throw ArgumentError("void is not a valid field type.");
    }
    return _getField<T>(
        callType, (ct) => _accessors.getField(reference, fieldID, ct));
  }

  /// Get value of the field identified by [name] and [signature].
  ///
  /// See [getField] for an explanation about [callType] parameter.
  T getFieldByName<T>(String name, String signature, [int? callType]) {
    final id = getFieldID(name, signature);
    return getField<T>(id, callType);
  }

  /// Get value of the static field using [fieldID].
  ///
  /// See [getField] for an explanation about [callType] parameter.
  T getStaticField<T>(JFieldIDPtr fieldID, [int? callType]) {
    if (callType == JniCallType.voidType) {
      throw ArgumentError("void is not a valid field type.");
    }
    _ensureNotDeleted();
    return _getField<T>(callType,
        (ct) => _accessors.getStaticField(_class.reference, fieldID, ct));
  }

  /// Get value of the static field identified by [name] and [signature].
  ///
  /// See [getField] for an explanation about [callType] parameter.
  T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
    final id = getStaticFieldID(name, signature);
    return getStaticField<T>(id, callType);
  }

  /// Call the method using [methodID],
  ///
  /// [args] can consist of primitive types, JNI primitive wrappers such as
  /// [JValueLong], strings, and subclasses of [JObject].
  ///
  /// See [getField] for an explanation about [callType] and return type [T].
  T callMethod<T>(JMethodIDPtr methodID, List<dynamic> args, [int? callType]) {
    _ensureNotDeleted();
    return _callMethod<T>(callType, args,
        (ct, jvs) => _accessors.callMethod(reference, methodID, ct, jvs));
  }

  /// Call instance method identified by [name] and [signature].
  ///
  /// This implementation looks up the method and calls it using [callMethod].
  T callMethodByName<T>(String name, String signature, List<dynamic> args,
      [int? callType]) {
    final id = getMethodID(name, signature);
    return callMethod<T>(id, args, callType);
  }

  /// Call static method using [methodID]. See [callMethod] and [getField] for
  /// more details about [args] and [callType].
  T callStaticMethod<T>(JMethodIDPtr methodID, List<dynamic> args,
      [int? callType]) {
    _ensureNotDeleted();
    return _callMethod<T>(callType, args,
        (ct, jvs) => _accessors.callStaticMethod(reference, methodID, ct, jvs));
  }

  /// Call static method identified by [name] and [signature].
  ///
  /// This implementation looks up the method and calls [callStaticMethod].
  T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
      [int? callType]) {
    final id = getStaticMethodID(name, signature);
    return callStaticMethod<T>(id, args, callType);
  }
}

/// A high level wrapper over a JNI class reference.
class JniClass extends JReference {
  /// Construct a new [JniClass] with [reference] as its underlying reference.
  JniClass.fromRef(JObjectPtr reference) : super.fromRef(reference);

  /// Get [JFieldIDPtr] of static field [fieldName] with [signature].
  JFieldIDPtr getStaticFieldID(String fieldName, String signature) {
    _ensureNotDeleted();
    return _getID<jfieldID_>(
        _accessors.getStaticFieldID, reference, fieldName, signature);
  }

  /// Get [JMethodIDPtr] of static method [methodName] with [signature].
  JMethodIDPtr getStaticMethodID(String methodName, String signature) {
    _ensureNotDeleted();
    return _getID<jmethodID_>(
        _accessors.getStaticMethodID, reference, methodName, signature);
  }

  /// Get [JFieldIDPtr] of field [fieldName] with [signature].
  JFieldIDPtr getFieldID(String fieldName, String signature) {
    _ensureNotDeleted();
    return _getID<jfieldID_>(
        _accessors.getFieldID, reference, fieldName, signature);
  }

  /// Get [JMethodIDPtr] of method [methodName] with [signature].
  JMethodIDPtr getMethodID(String methodName, String signature) {
    _ensureNotDeleted();
    return _getID<jmethodID_>(
        _accessors.getMethodID, reference, methodName, signature);
  }

  /// Get [JMethodIDPtr] of constructor with [signature].
  JMethodIDPtr getCtorID(String signature) => getMethodID("<init>", signature);

  /// Get the value of static field using [fieldID].
  ///
  /// See [JObject.getField] for more explanation about [callType].
  T getStaticField<T>(JFieldIDPtr fieldID, [int? callType]) {
    if (callType == JniCallType.voidType) {
      throw ArgumentError("void is not a valid field type.");
    }
    _ensureNotDeleted();
    return _getField<T>(
        callType, (ct) => _accessors.getStaticField(reference, fieldID, ct));
  }

  /// Get the value of static field identified by [name] and [signature].
  ///
  /// This implementation looks up the field ID and calls [getStaticField].
  T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
    final id = getStaticFieldID(name, signature);
    return getStaticField<T>(id, callType);
  }

  /// Call the static method using [methodID].
  ///
  /// See [JObject.callMethod] and [JObject.getField] for more explanation
  /// about [args] and [callType].
  T callStaticMethod<T>(JMethodIDPtr methodID, List<dynamic> args,
      [int? callType]) {
    _ensureNotDeleted();
    return _callMethod<T>(callType, args,
        (ct, jvs) => _accessors.callStaticMethod(reference, methodID, ct, jvs));
  }

  /// Call the static method identified by [name] and [signature].
  ///
  /// This implementation looks up the method ID and calls [callStaticMethod].
  T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
      [int? callType]) {
    final id = getStaticMethodID(name, signature);
    return callStaticMethod<T>(id, args, callType);
  }

  /// Create a new instance of this class with [ctor] and [args].
  JObject newInstance(JMethodIDPtr ctor, List<dynamic> args) => using((arena) {
        _ensureNotDeleted();
        final jArgs = JValueArgs(args, arena);
        arena.onReleaseAll(jArgs.dispose);
        final res = _accessors.newObject(reference, ctor, jArgs.values).object;
        return JObject.fromRef(res);
      });
}
