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

// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

// Auto-generated initialization code.

final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
    ProtectedJniExtensions.initGeneratedLibrary("kotlin");

/// from: com.github.dart_lang.jnigen.SuspendFun
class SuspendFun extends jni.JObject {
  @override
  late final jni.JObjType<SuspendFun> $type = type;

  SuspendFun.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $SuspendFunType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "SuspendFun__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory SuspendFun() {
    return SuspendFun.fromReference(_new0().reference);
  }

  static final _sayHello = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("SuspendFun__sayHello")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final java.lang.Object sayHello(kotlin.coroutines.Continuation continuation)
  /// The returned object must be released after use, by calling the [release] method.
  Future<jni.JString> sayHello() async {
    final $p = ReceivePort();
    final $c = jni.JObject.fromReference(
        ProtectedJniExtensions.newPortContinuation($p));
    _sayHello(reference.pointer, $c.reference.pointer)
        .object(const jni.JObjectType());
    final $o = jni.JGlobalReference(jni.JObjectPtr.fromAddress(await $p.first));
    final $k = const jni.JStringType().jClass.reference.pointer;
    if (!jni.Jni.env.IsInstanceOf($o.pointer, $k)) {
      throw "Failed";
    }
    return const jni.JStringType().fromReference($o);
  }

  static final _sayHello1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("SuspendFun__sayHello1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public final java.lang.Object sayHello(java.lang.String string, kotlin.coroutines.Continuation continuation)
  /// The returned object must be released after use, by calling the [release] method.
  Future<jni.JString> sayHello1(
    jni.JString string,
  ) async {
    final $p = ReceivePort();
    final $c = jni.JObject.fromReference(
        ProtectedJniExtensions.newPortContinuation($p));
    _sayHello1(
            reference.pointer, string.reference.pointer, $c.reference.pointer)
        .object(const jni.JObjectType());
    final $o = jni.JGlobalReference(jni.JObjectPtr.fromAddress(await $p.first));
    final $k = const jni.JStringType().jClass.reference.pointer;
    if (!jni.Jni.env.IsInstanceOf($o.pointer, $k)) {
      throw "Failed";
    }
    return const jni.JStringType().fromReference($o);
  }
}

final class $SuspendFunType extends jni.JObjType<SuspendFun> {
  const $SuspendFunType();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/SuspendFun;";

  @override
  SuspendFun fromReference(jni.JReference reference) =>
      SuspendFun.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($SuspendFunType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($SuspendFunType) && other is $SuspendFunType;
  }
}
