///
/// JLDP_PresentParams.hpp
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
/// https://github.com/mrousavy/nitro
/// Copyright © 2025 Marc Rousavy @ Margelo
///

#pragma once

#include <fbjni/fbjni.h>
#include "LDP_PresentParams.hpp"

#include "JFunc_void_LDP_Range.hpp"
#include "JFunc_void_std__string.hpp"
#include "JFunc_void_std__string_std__vector_std__string_.hpp"
#include "JLDP_PickerMode.hpp"
#include "JLDP_PriceData.hpp"
#include "JLDP_Range.hpp"
#include "LDP_PickerMode.hpp"
#include "LDP_PriceData.hpp"
#include "LDP_Range.hpp"
#include <functional>
#include <optional>
#include <string>
#include <vector>

namespace margelo::nitro::lunardatepicker {

  using namespace facebook;

  /**
   * The C++ JNI bridge between the C++ struct "LDP_PresentParams" and the the Kotlin data class "LDP_PresentParams".
   */
  struct JLDP_PresentParams final: public jni::JavaClass<JLDP_PresentParams> {
  public:
    static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/lunardatepicker/LDP_PresentParams;";

  public:
    /**
     * Convert this Java/Kotlin-based struct to the C++ struct LDP_PresentParams by copying all values to C++.
     */
    [[maybe_unused]]
    [[nodiscard]]
    LDP_PresentParams toCpp() const {
      static const auto clazz = javaClassStatic();
      static const auto fieldTheme = clazz->getField<jni::JString>("theme");
      jni::local_ref<jni::JString> theme = this->getFieldValue(fieldTheme);
      static const auto fieldLanguage = clazz->getField<jni::JString>("language");
      jni::local_ref<jni::JString> language = this->getFieldValue(fieldLanguage);
      static const auto fieldTitle = clazz->getField<jni::JString>("title");
      jni::local_ref<jni::JString> title = this->getFieldValue(fieldTitle);
      static const auto fieldTextCancel = clazz->getField<jni::JString>("textCancel");
      jni::local_ref<jni::JString> textCancel = this->getFieldValue(fieldTextCancel);
      static const auto fieldMode = clazz->getField<JLDP_PickerMode>("mode");
      jni::local_ref<JLDP_PickerMode> mode = this->getFieldValue(fieldMode);
      static const auto fieldOnDone = clazz->getField<JFunc_void_LDP_Range::javaobject>("onDone");
      jni::local_ref<JFunc_void_LDP_Range::javaobject> onDone = this->getFieldValue(fieldOnDone);
      static const auto fieldMinimumDate = clazz->getField<jni::JString>("minimumDate");
      jni::local_ref<jni::JString> minimumDate = this->getFieldValue(fieldMinimumDate);
      static const auto fieldMaximumDate = clazz->getField<jni::JString>("maximumDate");
      jni::local_ref<jni::JString> maximumDate = this->getFieldValue(fieldMaximumDate);
      static const auto fieldInitialValue = clazz->getField<JLDP_Range>("initialValue");
      jni::local_ref<JLDP_Range> initialValue = this->getFieldValue(fieldInitialValue);
      static const auto fieldPrices = clazz->getField<jni::JArrayClass<JLDP_PriceData>>("prices");
      jni::local_ref<jni::JArrayClass<JLDP_PriceData>> prices = this->getFieldValue(fieldPrices);
      static const auto fieldOnMonthVisible = clazz->getField<JFunc_void_std__string::javaobject>("onMonthVisible");
      jni::local_ref<JFunc_void_std__string::javaobject> onMonthVisible = this->getFieldValue(fieldOnMonthVisible);
      static const auto fieldOnSelectFromDate = clazz->getField<JFunc_void_std__string_std__vector_std__string_::javaobject>("onSelectFromDate");
      jni::local_ref<JFunc_void_std__string_std__vector_std__string_::javaobject> onSelectFromDate = this->getFieldValue(fieldOnSelectFromDate);
      return LDP_PresentParams(
        theme->toStdString(),
        language->toStdString(),
        title->toStdString(),
        textCancel->toStdString(),
        mode->toCpp(),
        [&]() -> std::function<void(const LDP_Range& /* result */)> {
          if (onDone->isInstanceOf(JFunc_void_LDP_Range_cxx::javaClassStatic())) [[likely]] {
            auto downcast = jni::static_ref_cast<JFunc_void_LDP_Range_cxx::javaobject>(onDone);
            return downcast->cthis()->getFunction();
          } else {
            auto onDoneRef = jni::make_global(onDone);
            return [onDoneRef](LDP_Range result) -> void {
              return onDoneRef->invoke(result);
            };
          }
        }(),
        minimumDate != nullptr ? std::make_optional(minimumDate->toStdString()) : std::nullopt,
        maximumDate != nullptr ? std::make_optional(maximumDate->toStdString()) : std::nullopt,
        initialValue != nullptr ? std::make_optional(initialValue->toCpp()) : std::nullopt,
        prices != nullptr ? std::make_optional([&]() {
          size_t __size = prices->size();
          std::vector<LDP_PriceData> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = prices->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        onMonthVisible != nullptr ? std::make_optional([&]() -> std::function<void(const std::string& /* month */)> {
          if (onMonthVisible->isInstanceOf(JFunc_void_std__string_cxx::javaClassStatic())) [[likely]] {
            auto downcast = jni::static_ref_cast<JFunc_void_std__string_cxx::javaobject>(onMonthVisible);
            return downcast->cthis()->getFunction();
          } else {
            auto onMonthVisibleRef = jni::make_global(onMonthVisible);
            return [onMonthVisibleRef](std::string month) -> void {
              return onMonthVisibleRef->invoke(month);
            };
          }
        }()) : std::nullopt,
        onSelectFromDate != nullptr ? std::make_optional([&]() -> std::function<void(const std::string& /* date */, const std::vector<std::string>& /* currentlyVisibleMonths */)> {
          if (onSelectFromDate->isInstanceOf(JFunc_void_std__string_std__vector_std__string__cxx::javaClassStatic())) [[likely]] {
            auto downcast = jni::static_ref_cast<JFunc_void_std__string_std__vector_std__string__cxx::javaobject>(onSelectFromDate);
            return downcast->cthis()->getFunction();
          } else {
            auto onSelectFromDateRef = jni::make_global(onSelectFromDate);
            return [onSelectFromDateRef](std::string date, std::vector<std::string> currentlyVisibleMonths) -> void {
              return onSelectFromDateRef->invoke(date,currentlyVisibleMonths);
            };
          }
        }()) : std::nullopt
      );
    }

  public:
    /**
     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
     */
    [[maybe_unused]]
    static jni::local_ref<JLDP_PresentParams::javaobject> fromCpp(const LDP_PresentParams& value) {
      return newInstance(
        jni::make_jstring(value.theme),
        jni::make_jstring(value.language),
        jni::make_jstring(value.title),
        jni::make_jstring(value.textCancel),
        JLDP_PickerMode::fromCpp(value.mode),
        JFunc_void_LDP_Range_cxx::fromCpp(value.onDone),
        value.minimumDate.has_value() ? jni::make_jstring(value.minimumDate.value()) : nullptr,
        value.maximumDate.has_value() ? jni::make_jstring(value.maximumDate.value()) : nullptr,
        value.initialValue.has_value() ? JLDP_Range::fromCpp(value.initialValue.value()) : nullptr,
        value.prices.has_value() ? [&]() {
          size_t __size = value.prices.value().size();
          jni::local_ref<jni::JArrayClass<JLDP_PriceData>> __array = jni::JArrayClass<JLDP_PriceData>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.prices.value()[__i];
            __array->setElement(__i, *JLDP_PriceData::fromCpp(__element));
          }
          return __array;
        }() : nullptr,
        value.onMonthVisible.has_value() ? JFunc_void_std__string_cxx::fromCpp(value.onMonthVisible.value()) : nullptr,
        value.onSelectFromDate.has_value() ? JFunc_void_std__string_std__vector_std__string__cxx::fromCpp(value.onSelectFromDate.value()) : nullptr
      );
    }
  };

} // namespace margelo::nitro::lunardatepicker
