// This file was generated by
//     //third_party/jni_zero/jni_zero.py
// For
//     org.jni_zero.SampleGenerics

#ifndef org_jni_1zero_SampleGenerics_JNI
#define org_jni_1zero_SampleGenerics_JNI

#include <jni.h>

#include "overridden/jni_zero_internal.h"
#include "extra_include.h"
#include "SampleGenerics_shared_jni.h"

// Field, class, and method accessors use inline functions with static
// variables for caching.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunique-object-duplication"

// Example signatures (to be implemented by #including file).
// * JNIEnv* parameters are optional.
// * Types do not have to be exact; they must accept rvalues of the examples.
//
// static void JNI_SampleGenerics_MethodWithGenericParam(
//     JNIEnv* env,
//     const jni_zero::JavaRef<::java::util::JList<jstring>>& arg);
//
// static jni_zero::ScopedJavaLocalRef<::org::jni_zero::JSampleGenerics<::java::util::JList<jstring>>> JNI_SampleGenerics_SomeMethod(
//     JNIEnv* env,
//     const jni_zero::JavaRef<::org::jni_zero::JSampleGenerics<::java::util::JList<jstring>>>& arg,
//     const jni_zero::JavaRef<::java::util::JList<jstring>>& arg2);
//

// Triggers a compiler warning if DEFINE_JNI(SampleGenerics) is forgotten (requires -Wunused-function).
static void YouForgotToCallMacro_DEFINE_JNI_SampleGenerics() {}

// Java to native functions
#define DEFINE_JNI_FOR_SampleGenerics()                                                            \
  namespace {                                                                                      \
                                                                                                   \
  using namespace jni_zero;                                                                        \
  JNI_ZERO_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleGenerics_1methodWithGenericParam( \
      JNIEnv* env,                                                                                 \
      jclass jcaller,                                                                              \
      jobject arg) {                                                                               \
    /* Prevent -Wunused-function warning. */                                                       \
    YouForgotToCallMacro_DEFINE_JNI_SampleGenerics();                                              \
                                                                                                   \
    auto arg_ref = jni_zero::JavaRef<::java::util::JList<jstring>>::CreateLeaky(env,               \
        static_cast<::java::util::JList<jstring>>(arg));                                           \
    /* Lambda required to make "if constexpr" work properly. */                                    \
    auto dependent_context = [&](auto) {                                                           \
      /* Lambda required to disambiguate overloads. */                                             \
      auto func_wrapper = [&](auto&&... args) ->                                                   \
      decltype(JNI_SampleGenerics_MethodWithGenericParam(std::forward<decltype(args)>(args)...)) { \
        return JNI_SampleGenerics_MethodWithGenericParam(std::forward<decltype(args)>(args)...);   \
      };                                                                                           \
      if constexpr (requires { func_wrapper(env, arg_ref); }) {                                    \
        return func_wrapper(env, arg_ref);                                                         \
      } else if constexpr (requires { func_wrapper(arg_ref); }) {                                  \
        return func_wrapper(arg_ref);                                                              \
      } else {                                                                                     \
        static_assert(false, "JNI_SampleGenerics_MethodWithGenericParam() is missing or has incorrect signature.\nIt should accept an optional JNIEnv* parameter as well as rvalues of the given types: (const jni_zero::JavaRef<JList<jstring>>&)\nSee SampleGenerics_jni.h for an example."); \
      }                                                                                            \
    };                                                                                             \
    dependent_context(0);                                                                          \
  }                                                                                                \
                                                                                                   \
  JNI_ZERO_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleGenerics_1someMethod( \
      JNIEnv* env,                                                                                 \
      jclass jcaller,                                                                              \
      jobject arg,                                                                                 \
      jobject arg2) {                                                                              \
    auto arg_ref = jni_zero::JavaRef<::org::jni_zero::JSampleGenerics<::java::util::JList<jstring>>>::CreateLeaky(env, \
        static_cast<::org::jni_zero::JSampleGenerics<::java::util::JList<jstring>>>(arg));         \
    auto arg2_ref = jni_zero::JavaRef<::java::util::JList<jstring>>::CreateLeaky(env,              \
        static_cast<::java::util::JList<jstring>>(arg2));                                          \
    /* Lambda required to make "if constexpr" work properly. */                                    \
    auto dependent_context = [&](auto) {                                                           \
      /* Lambda required to disambiguate overloads. */                                             \
      auto func_wrapper = [&](auto&&... args) ->                                                   \
      decltype(JNI_SampleGenerics_SomeMethod(std::forward<decltype(args)>(args)...)) {             \
        return JNI_SampleGenerics_SomeMethod(std::forward<decltype(args)>(args)...);               \
      };                                                                                           \
      if constexpr (requires { func_wrapper(env, arg_ref, arg2_ref); }) {                          \
        return func_wrapper(env, arg_ref, arg2_ref);                                               \
      } else if constexpr (requires { func_wrapper(arg_ref, arg2_ref); }) {                        \
        return func_wrapper(arg_ref, arg2_ref);                                                    \
      } else {                                                                                     \
        static_assert(false, "JNI_SampleGenerics_SomeMethod() is missing or has incorrect signature.\nIt should accept an optional JNIEnv* parameter as well as rvalues of the given types: (const jni_zero::JavaRef<JSampleGenerics<JList<jstring>>>&, const jni_zero::JavaRef<JList<jstring>>&)\nSee SampleGenerics_jni.h for an example."); \
      }                                                                                            \
    };                                                                                             \
    auto return_value = dependent_context(0);                                                      \
    return return_value.ReleaseLocal();                                                            \
  }                                                                                                \
                                                                                                   \
                                                                                                   \
  }  /* namespace */

// Class Accessors
#ifndef org_jni_1zero_SampleGenerics_clazz_defined
#define org_jni_1zero_SampleGenerics_clazz_defined
inline jclass org_jni_1zero_SampleGenerics_clazz(JNIEnv* env) {
  static const char kClassName[] = "org.jni_zero.SampleGenerics";
  static std::atomic<jclass> cached_class;
  return jni_zero::internal::LazyGetClass(env, kClassName, &cached_class);
}
#endif


namespace jni_zero {

// Native to Java functions
static ::jni_zero::ScopedJavaLocalRef<jobject> Java_SampleGenerics_Constructor__int(
    JNIEnv* env,
    JniIntWrapper noMethodGenerics) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleGenerics_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  ::jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<::jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "<init>",
      "(I)V",
      &cached_method_id);
  auto _ret = env->NewObject(clazz, call_context.method_id(), as_jint(noMethodGenerics));
  return ::jni_zero::ScopedJavaLocalRef<jobject>::Adopt(env, _ret);
}

static ::jni_zero::ScopedJavaLocalRef<jobject> Java_SampleGenerics_Constructor__T2(
    JNIEnv* env,
    const ::jni_zero::JavaRef<jobject>& mustMergeGenerics) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleGenerics_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  ::jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<::jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "<init>",
      "(Ljava/lang/Object;)V",
      &cached_method_id);
  auto _ret = env->NewObject(clazz, call_context.method_id(), mustMergeGenerics.obj());
  return ::jni_zero::ScopedJavaLocalRef<jobject>::Adopt(env, _ret);
}

static ::jni_zero::ScopedJavaLocalRef<jobject> Java_SampleGenerics_someMethod(
    JNIEnv* env,
    const ::jni_zero::JavaRef<jobject>& obj,
    const ::jni_zero::JavaRef<jobject>& someArg) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleGenerics_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, nullptr);
  ::jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<::jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "someMethod",
      "(Ljava/util/List;)Ljava/util/List;",
      &cached_method_id);
  auto _ret = env->CallObjectMethod(obj.obj(), call_context.method_id(), someArg.obj());
  return ::jni_zero::ScopedJavaLocalRef<jobject>::Adopt(env, _ret);
}



}  // namespace jni_zero

// jobject-subclass-aware definitions:
namespace jni_zero_internal {

using namespace ::jni_zero;

template<>
class _CalledByNativesStatics<::org::jni_zero::JSampleGenerics<jobject>> {
  public:
  template <typename T>
  static ::jni_zero::ScopedJavaLocalRef<::org::jni_zero::JSampleGenerics<T>> New(
      JNIEnv* env,
      JniIntWrapper noMethodGenerics) {
    return Java_SampleGenerics_Constructor__int(env, noMethodGenerics)
        .template As<::org::jni_zero::JSampleGenerics<T>>();
  }

  template <typename T, typename T2>
  static ::jni_zero::ScopedJavaLocalRef<::org::jni_zero::JSampleGenerics<T>> New(
      JNIEnv* env,
      const ::jni_zero::JavaRef<T2>& mustMergeGenerics) {
    return Java_SampleGenerics_Constructor__T2(env, mustMergeGenerics)
        .template As<::org::jni_zero::JSampleGenerics<T>>();
  }

};

template <typename T>
class _CalledByNatives<::org::jni_zero::JSampleGenerics<T>> {
  public:
  ::jni_zero::ScopedJavaLocalRef<T> someMethod(JNIEnv* env, const ::jni_zero::JavaRef<T>& someArg) const {
    auto this_obj = reinterpret_cast<const ::jni_zero::JavaRef<::org::jni_zero::JSampleGenerics<T>>*>(this);
    return Java_SampleGenerics_someMethod(env, *this_obj, someArg)
        .template As<T>();
  }

};


}  // namespace jni_zero_internal

namespace org::jni_zero {
using SampleGenericsJni = ::jni_zero_internal::_CalledByNativesStatics<::org::jni_zero::JSampleGenerics<jobject>>;
}
#ifndef _JNI_ZERO_SampleGenericsJni_DEFINED
#define _JNI_ZERO_SampleGenericsJni_DEFINED
using ::org::jni_zero::SampleGenericsJni;
#endif


#pragma clang diagnostic pop
#endif  // org_jni_1zero_SampleGenerics_JNI
