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

#pragma once

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

#include "JMailAddressStruct.hpp"
#include "MailAddressStruct.hpp"
#include <optional>
#include <string>
#include <vector>

namespace margelo::nitro::mailengine {

  using namespace facebook;

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

  public:
    /**
     * Convert this Java/Kotlin-based struct to the C++ struct MailHeaderStruct by copying all values to C++.
     */
    [[maybe_unused]]
    [[nodiscard]]
    MailHeaderStruct toCpp() const {
      static const auto clazz = javaClassStatic();
      static const auto fieldUid = clazz->getField<double>("uid");
      double uid = this->getFieldValue(fieldUid);
      static const auto fieldMessageId = clazz->getField<jni::JString>("messageId");
      jni::local_ref<jni::JString> messageId = this->getFieldValue(fieldMessageId);
      static const auto fieldSubject = clazz->getField<jni::JString>("subject");
      jni::local_ref<jni::JString> subject = this->getFieldValue(fieldSubject);
      static const auto fieldFrom = clazz->getField<jni::JArrayClass<JMailAddressStruct>>("from");
      jni::local_ref<jni::JArrayClass<JMailAddressStruct>> from = this->getFieldValue(fieldFrom);
      static const auto fieldTo = clazz->getField<jni::JArrayClass<JMailAddressStruct>>("to");
      jni::local_ref<jni::JArrayClass<JMailAddressStruct>> to = this->getFieldValue(fieldTo);
      static const auto fieldCc = clazz->getField<jni::JArrayClass<JMailAddressStruct>>("cc");
      jni::local_ref<jni::JArrayClass<JMailAddressStruct>> cc = this->getFieldValue(fieldCc);
      static const auto fieldBcc = clazz->getField<jni::JArrayClass<JMailAddressStruct>>("bcc");
      jni::local_ref<jni::JArrayClass<JMailAddressStruct>> bcc = this->getFieldValue(fieldBcc);
      static const auto fieldReplyTo = clazz->getField<jni::JArrayClass<JMailAddressStruct>>("replyTo");
      jni::local_ref<jni::JArrayClass<JMailAddressStruct>> replyTo = this->getFieldValue(fieldReplyTo);
      static const auto fieldDate = clazz->getField<jni::JDouble>("date");
      jni::local_ref<jni::JDouble> date = this->getFieldValue(fieldDate);
      static const auto fieldFlags = clazz->getField<jni::JArrayClass<jni::JString>>("flags");
      jni::local_ref<jni::JArrayClass<jni::JString>> flags = this->getFieldValue(fieldFlags);
      static const auto fieldSize = clazz->getField<jni::JDouble>("size");
      jni::local_ref<jni::JDouble> size = this->getFieldValue(fieldSize);
      static const auto fieldHasAttachments = clazz->getField<jboolean>("hasAttachments");
      jboolean hasAttachments = this->getFieldValue(fieldHasAttachments);
      static const auto fieldInReplyTo = clazz->getField<jni::JString>("inReplyTo");
      jni::local_ref<jni::JString> inReplyTo = this->getFieldValue(fieldInReplyTo);
      static const auto fieldReferences = clazz->getField<jni::JArrayClass<jni::JString>>("references");
      jni::local_ref<jni::JArrayClass<jni::JString>> references = this->getFieldValue(fieldReferences);
      static const auto fieldPreview = clazz->getField<jni::JString>("preview");
      jni::local_ref<jni::JString> preview = this->getFieldValue(fieldPreview);
      return MailHeaderStruct(
        uid,
        messageId != nullptr ? std::make_optional(messageId->toStdString()) : std::nullopt,
        subject != nullptr ? std::make_optional(subject->toStdString()) : std::nullopt,
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailAddressStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(from),
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailAddressStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(to),
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailAddressStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(cc),
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailAddressStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(bcc),
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailAddressStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(replyTo),
        date != nullptr ? std::make_optional(date->value()) : std::nullopt,
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<std::string> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toStdString());
          }
          return __vector;
        }(flags),
        size != nullptr ? std::make_optional(size->value()) : std::nullopt,
        static_cast<bool>(hasAttachments),
        inReplyTo != nullptr ? std::make_optional(inReplyTo->toStdString()) : std::nullopt,
        [&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<std::string> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toStdString());
          }
          return __vector;
        }(references),
        preview != nullptr ? std::make_optional(preview->toStdString()) : 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<JMailHeaderStruct::javaobject> fromCpp(const MailHeaderStruct& value) {
      using JSignature = JMailHeaderStruct(double, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JArrayClass<JMailAddressStruct>>, jni::alias_ref<jni::JArrayClass<JMailAddressStruct>>, jni::alias_ref<jni::JArrayClass<JMailAddressStruct>>, jni::alias_ref<jni::JArrayClass<JMailAddressStruct>>, jni::alias_ref<jni::JArrayClass<JMailAddressStruct>>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JArrayClass<jni::JString>>, jni::alias_ref<jni::JDouble>, jboolean, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JArrayClass<jni::JString>>, jni::alias_ref<jni::JString>);
      static const auto clazz = javaClassStatic();
      static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
      return create(
        clazz,
        value.uid,
        value.messageId.has_value() ? jni::make_jstring(value.messageId.value()) : nullptr,
        value.subject.has_value() ? jni::make_jstring(value.subject.value()) : nullptr,
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JMailAddressStruct>> __array = jni::JArrayClass<JMailAddressStruct>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JMailAddressStruct::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.from),
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JMailAddressStruct>> __array = jni::JArrayClass<JMailAddressStruct>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JMailAddressStruct::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.to),
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JMailAddressStruct>> __array = jni::JArrayClass<JMailAddressStruct>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JMailAddressStruct::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.cc),
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JMailAddressStruct>> __array = jni::JArrayClass<JMailAddressStruct>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JMailAddressStruct::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.bcc),
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JMailAddressStruct>> __array = jni::JArrayClass<JMailAddressStruct>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JMailAddressStruct::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.replyTo),
        value.date.has_value() ? jni::JDouble::valueOf(value.date.value()) : nullptr,
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<jni::JString>> __array = jni::JArrayClass<jni::JString>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = jni::make_jstring(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.flags),
        value.size.has_value() ? jni::JDouble::valueOf(value.size.value()) : nullptr,
        value.hasAttachments,
        value.inReplyTo.has_value() ? jni::make_jstring(value.inReplyTo.value()) : nullptr,
        [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<jni::JString>> __array = jni::JArrayClass<jni::JString>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = jni::make_jstring(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.references),
        value.preview.has_value() ? jni::make_jstring(value.preview.value()) : nullptr
      );
    }
  };

} // namespace margelo::nitro::mailengine
