///
/// JPublicationMetadata.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 "PublicationMetadata.hpp"

#include "Accessibility.hpp"
#include "AccessibilityCertification.hpp"
#include "BelongsTo.hpp"
#include "Contributor.hpp"
#include "JAccessibility.hpp"
#include "JAccessibilityCertification.hpp"
#include "JBelongsTo.hpp"
#include "JContributor.hpp"
#include "JSeriesInfo.hpp"
#include "JSubject.hpp"
#include "SeriesInfo.hpp"
#include "Subject.hpp"
#include <optional>
#include <string>
#include <vector>

namespace margelo::nitro::readium {

  using namespace facebook;

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

  public:
    /**
     * Convert this Java/Kotlin-based struct to the C++ struct PublicationMetadata by copying all values to C++.
     */
    [[maybe_unused]]
    [[nodiscard]]
    PublicationMetadata toCpp() const {
      static const auto clazz = javaClassStatic();
      static const auto fieldTitle = clazz->getField<jni::JString>("title");
      jni::local_ref<jni::JString> title = this->getFieldValue(fieldTitle);
      static const auto fieldSortAs = clazz->getField<jni::JString>("sortAs");
      jni::local_ref<jni::JString> sortAs = this->getFieldValue(fieldSortAs);
      static const auto fieldSubtitle = clazz->getField<jni::JString>("subtitle");
      jni::local_ref<jni::JString> subtitle = this->getFieldValue(fieldSubtitle);
      static const auto fieldIdentifier = clazz->getField<jni::JString>("identifier");
      jni::local_ref<jni::JString> identifier = this->getFieldValue(fieldIdentifier);
      static const auto fieldAccessibility = clazz->getField<JAccessibility>("accessibility");
      jni::local_ref<JAccessibility> accessibility = this->getFieldValue(fieldAccessibility);
      static const auto fieldModified = clazz->getField<jni::JString>("modified");
      jni::local_ref<jni::JString> modified = this->getFieldValue(fieldModified);
      static const auto fieldPublished = clazz->getField<jni::JString>("published");
      jni::local_ref<jni::JString> published = this->getFieldValue(fieldPublished);
      static const auto fieldLanguage = clazz->getField<jni::JArrayClass<jni::JString>>("language");
      jni::local_ref<jni::JArrayClass<jni::JString>> language = this->getFieldValue(fieldLanguage);
      static const auto fieldAuthor = clazz->getField<jni::JArrayClass<JContributor>>("author");
      jni::local_ref<jni::JArrayClass<JContributor>> author = this->getFieldValue(fieldAuthor);
      static const auto fieldTranslator = clazz->getField<jni::JArrayClass<JContributor>>("translator");
      jni::local_ref<jni::JArrayClass<JContributor>> translator = this->getFieldValue(fieldTranslator);
      static const auto fieldEditor = clazz->getField<jni::JArrayClass<JContributor>>("editor");
      jni::local_ref<jni::JArrayClass<JContributor>> editor = this->getFieldValue(fieldEditor);
      static const auto fieldArtist = clazz->getField<jni::JArrayClass<JContributor>>("artist");
      jni::local_ref<jni::JArrayClass<JContributor>> artist = this->getFieldValue(fieldArtist);
      static const auto fieldIllustrator = clazz->getField<jni::JArrayClass<JContributor>>("illustrator");
      jni::local_ref<jni::JArrayClass<JContributor>> illustrator = this->getFieldValue(fieldIllustrator);
      static const auto fieldLetterer = clazz->getField<jni::JArrayClass<JContributor>>("letterer");
      jni::local_ref<jni::JArrayClass<JContributor>> letterer = this->getFieldValue(fieldLetterer);
      static const auto fieldPenciler = clazz->getField<jni::JArrayClass<JContributor>>("penciler");
      jni::local_ref<jni::JArrayClass<JContributor>> penciler = this->getFieldValue(fieldPenciler);
      static const auto fieldColorist = clazz->getField<jni::JArrayClass<JContributor>>("colorist");
      jni::local_ref<jni::JArrayClass<JContributor>> colorist = this->getFieldValue(fieldColorist);
      static const auto fieldInker = clazz->getField<jni::JArrayClass<JContributor>>("inker");
      jni::local_ref<jni::JArrayClass<JContributor>> inker = this->getFieldValue(fieldInker);
      static const auto fieldNarrator = clazz->getField<jni::JArrayClass<JContributor>>("narrator");
      jni::local_ref<jni::JArrayClass<JContributor>> narrator = this->getFieldValue(fieldNarrator);
      static const auto fieldContributor = clazz->getField<jni::JArrayClass<JContributor>>("contributor");
      jni::local_ref<jni::JArrayClass<JContributor>> contributor = this->getFieldValue(fieldContributor);
      static const auto fieldPublisher = clazz->getField<jni::JArrayClass<JContributor>>("publisher");
      jni::local_ref<jni::JArrayClass<JContributor>> publisher = this->getFieldValue(fieldPublisher);
      static const auto fieldImprint = clazz->getField<jni::JArrayClass<JContributor>>("imprint");
      jni::local_ref<jni::JArrayClass<JContributor>> imprint = this->getFieldValue(fieldImprint);
      static const auto fieldSubject = clazz->getField<jni::JArrayClass<JSubject>>("subject");
      jni::local_ref<jni::JArrayClass<JSubject>> subject = this->getFieldValue(fieldSubject);
      static const auto fieldLayout = clazz->getField<jni::JString>("layout");
      jni::local_ref<jni::JString> layout = this->getFieldValue(fieldLayout);
      static const auto fieldReadingProgression = clazz->getField<jni::JString>("readingProgression");
      jni::local_ref<jni::JString> readingProgression = this->getFieldValue(fieldReadingProgression);
      static const auto fieldDescription = clazz->getField<jni::JString>("description");
      jni::local_ref<jni::JString> description = this->getFieldValue(fieldDescription);
      static const auto fieldDuration = clazz->getField<jni::JDouble>("duration");
      jni::local_ref<jni::JDouble> duration = this->getFieldValue(fieldDuration);
      static const auto fieldNumberOfPages = clazz->getField<jni::JDouble>("numberOfPages");
      jni::local_ref<jni::JDouble> numberOfPages = this->getFieldValue(fieldNumberOfPages);
      static const auto fieldBelongsTo = clazz->getField<JBelongsTo>("belongsTo");
      jni::local_ref<JBelongsTo> belongsTo = this->getFieldValue(fieldBelongsTo);
      return PublicationMetadata(
        title->toStdString(),
        sortAs != nullptr ? std::make_optional(sortAs->toStdString()) : std::nullopt,
        subtitle != nullptr ? std::make_optional(subtitle->toStdString()) : std::nullopt,
        identifier != nullptr ? std::make_optional(identifier->toStdString()) : std::nullopt,
        accessibility != nullptr ? std::make_optional(accessibility->toCpp()) : std::nullopt,
        modified != nullptr ? std::make_optional(modified->toStdString()) : std::nullopt,
        published != nullptr ? std::make_optional(published->toStdString()) : std::nullopt,
        language != nullptr ? std::make_optional([&]() {
          size_t __size = language->size();
          std::vector<std::string> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = language->getElement(__i);
            __vector.push_back(__element->toStdString());
          }
          return __vector;
        }()) : std::nullopt,
        author != nullptr ? std::make_optional([&]() {
          size_t __size = author->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = author->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        translator != nullptr ? std::make_optional([&]() {
          size_t __size = translator->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = translator->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        editor != nullptr ? std::make_optional([&]() {
          size_t __size = editor->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = editor->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        artist != nullptr ? std::make_optional([&]() {
          size_t __size = artist->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = artist->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        illustrator != nullptr ? std::make_optional([&]() {
          size_t __size = illustrator->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = illustrator->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        letterer != nullptr ? std::make_optional([&]() {
          size_t __size = letterer->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = letterer->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        penciler != nullptr ? std::make_optional([&]() {
          size_t __size = penciler->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = penciler->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        colorist != nullptr ? std::make_optional([&]() {
          size_t __size = colorist->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = colorist->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        inker != nullptr ? std::make_optional([&]() {
          size_t __size = inker->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = inker->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        narrator != nullptr ? std::make_optional([&]() {
          size_t __size = narrator->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = narrator->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        contributor != nullptr ? std::make_optional([&]() {
          size_t __size = contributor->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = contributor->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        publisher != nullptr ? std::make_optional([&]() {
          size_t __size = publisher->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = publisher->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        imprint != nullptr ? std::make_optional([&]() {
          size_t __size = imprint->size();
          std::vector<Contributor> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = imprint->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        subject != nullptr ? std::make_optional([&]() {
          size_t __size = subject->size();
          std::vector<Subject> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = subject->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }()) : std::nullopt,
        layout != nullptr ? std::make_optional(layout->toStdString()) : std::nullopt,
        readingProgression != nullptr ? std::make_optional(readingProgression->toStdString()) : std::nullopt,
        description != nullptr ? std::make_optional(description->toStdString()) : std::nullopt,
        duration != nullptr ? std::make_optional(duration->value()) : std::nullopt,
        numberOfPages != nullptr ? std::make_optional(numberOfPages->value()) : std::nullopt,
        belongsTo != nullptr ? std::make_optional(belongsTo->toCpp()) : 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<JPublicationMetadata::javaobject> fromCpp(const PublicationMetadata& value) {
      using JSignature = JPublicationMetadata(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<JAccessibility>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JArrayClass<jni::JString>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JContributor>>, jni::alias_ref<jni::JArrayClass<JSubject>>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JBelongsTo>);
      static const auto clazz = javaClassStatic();
      static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
      return create(
        clazz,
        jni::make_jstring(value.title),
        value.sortAs.has_value() ? jni::make_jstring(value.sortAs.value()) : nullptr,
        value.subtitle.has_value() ? jni::make_jstring(value.subtitle.value()) : nullptr,
        value.identifier.has_value() ? jni::make_jstring(value.identifier.value()) : nullptr,
        value.accessibility.has_value() ? JAccessibility::fromCpp(value.accessibility.value()) : nullptr,
        value.modified.has_value() ? jni::make_jstring(value.modified.value()) : nullptr,
        value.published.has_value() ? jni::make_jstring(value.published.value()) : nullptr,
        value.language.has_value() ? [&]() {
          size_t __size = value.language.value().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 = value.language.value()[__i];
            auto __elementJni = jni::make_jstring(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.author.has_value() ? [&]() {
          size_t __size = value.author.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.author.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.translator.has_value() ? [&]() {
          size_t __size = value.translator.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.translator.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.editor.has_value() ? [&]() {
          size_t __size = value.editor.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.editor.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.artist.has_value() ? [&]() {
          size_t __size = value.artist.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.artist.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.illustrator.has_value() ? [&]() {
          size_t __size = value.illustrator.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.illustrator.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.letterer.has_value() ? [&]() {
          size_t __size = value.letterer.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.letterer.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.penciler.has_value() ? [&]() {
          size_t __size = value.penciler.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.penciler.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.colorist.has_value() ? [&]() {
          size_t __size = value.colorist.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.colorist.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.inker.has_value() ? [&]() {
          size_t __size = value.inker.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.inker.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.narrator.has_value() ? [&]() {
          size_t __size = value.narrator.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.narrator.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.contributor.has_value() ? [&]() {
          size_t __size = value.contributor.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.contributor.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.publisher.has_value() ? [&]() {
          size_t __size = value.publisher.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.publisher.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.imprint.has_value() ? [&]() {
          size_t __size = value.imprint.value().size();
          jni::local_ref<jni::JArrayClass<JContributor>> __array = jni::JArrayClass<JContributor>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.imprint.value()[__i];
            auto __elementJni = JContributor::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.subject.has_value() ? [&]() {
          size_t __size = value.subject.value().size();
          jni::local_ref<jni::JArrayClass<JSubject>> __array = jni::JArrayClass<JSubject>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = value.subject.value()[__i];
            auto __elementJni = JSubject::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }() : nullptr,
        value.layout.has_value() ? jni::make_jstring(value.layout.value()) : nullptr,
        value.readingProgression.has_value() ? jni::make_jstring(value.readingProgression.value()) : nullptr,
        value.description.has_value() ? jni::make_jstring(value.description.value()) : nullptr,
        value.duration.has_value() ? jni::JDouble::valueOf(value.duration.value()) : nullptr,
        value.numberOfPages.has_value() ? jni::JDouble::valueOf(value.numberOfPages.value()) : nullptr,
        value.belongsTo.has_value() ? JBelongsTo::fromCpp(value.belongsTo.value()) : nullptr
      );
    }
  };

} // namespace margelo::nitro::readium
