///
/// JContours.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 "Contours.hpp"

#include "JPoint.hpp"
#include "Point.hpp"
#include <optional>
#include <vector>

namespace margelo::nitro::camera::facedetector {

  using namespace facebook;

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

  public:
    /**
     * Convert this Java/Kotlin-based struct to the C++ struct Contours by copying all values to C++.
     */
    [[maybe_unused]]
    [[nodiscard]]
    Contours toCpp() const {
      static const auto clazz = javaClassStatic();
      static const auto fieldFACE = clazz->getField<jni::JArrayClass<JPoint>>("FACE");
      jni::local_ref<jni::JArrayClass<JPoint>> FACE = this->getFieldValue(fieldFACE);
      static const auto fieldLEFT_EYEBROW_TOP = clazz->getField<jni::JArrayClass<JPoint>>("LEFT_EYEBROW_TOP");
      jni::local_ref<jni::JArrayClass<JPoint>> LEFT_EYEBROW_TOP = this->getFieldValue(fieldLEFT_EYEBROW_TOP);
      static const auto fieldLEFT_EYEBROW_BOTTOM = clazz->getField<jni::JArrayClass<JPoint>>("LEFT_EYEBROW_BOTTOM");
      jni::local_ref<jni::JArrayClass<JPoint>> LEFT_EYEBROW_BOTTOM = this->getFieldValue(fieldLEFT_EYEBROW_BOTTOM);
      static const auto fieldRIGHT_EYEBROW_TOP = clazz->getField<jni::JArrayClass<JPoint>>("RIGHT_EYEBROW_TOP");
      jni::local_ref<jni::JArrayClass<JPoint>> RIGHT_EYEBROW_TOP = this->getFieldValue(fieldRIGHT_EYEBROW_TOP);
      static const auto fieldRIGHT_EYEBROW_BOTTOM = clazz->getField<jni::JArrayClass<JPoint>>("RIGHT_EYEBROW_BOTTOM");
      jni::local_ref<jni::JArrayClass<JPoint>> RIGHT_EYEBROW_BOTTOM = this->getFieldValue(fieldRIGHT_EYEBROW_BOTTOM);
      static const auto fieldLEFT_EYE = clazz->getField<jni::JArrayClass<JPoint>>("LEFT_EYE");
      jni::local_ref<jni::JArrayClass<JPoint>> LEFT_EYE = this->getFieldValue(fieldLEFT_EYE);
      static const auto fieldRIGHT_EYE = clazz->getField<jni::JArrayClass<JPoint>>("RIGHT_EYE");
      jni::local_ref<jni::JArrayClass<JPoint>> RIGHT_EYE = this->getFieldValue(fieldRIGHT_EYE);
      static const auto fieldUPPER_LIP_TOP = clazz->getField<jni::JArrayClass<JPoint>>("UPPER_LIP_TOP");
      jni::local_ref<jni::JArrayClass<JPoint>> UPPER_LIP_TOP = this->getFieldValue(fieldUPPER_LIP_TOP);
      static const auto fieldUPPER_LIP_BOTTOM = clazz->getField<jni::JArrayClass<JPoint>>("UPPER_LIP_BOTTOM");
      jni::local_ref<jni::JArrayClass<JPoint>> UPPER_LIP_BOTTOM = this->getFieldValue(fieldUPPER_LIP_BOTTOM);
      static const auto fieldLOWER_LIP_TOP = clazz->getField<jni::JArrayClass<JPoint>>("LOWER_LIP_TOP");
      jni::local_ref<jni::JArrayClass<JPoint>> LOWER_LIP_TOP = this->getFieldValue(fieldLOWER_LIP_TOP);
      static const auto fieldLOWER_LIP_BOTTOM = clazz->getField<jni::JArrayClass<JPoint>>("LOWER_LIP_BOTTOM");
      jni::local_ref<jni::JArrayClass<JPoint>> LOWER_LIP_BOTTOM = this->getFieldValue(fieldLOWER_LIP_BOTTOM);
      static const auto fieldNOSE_BRIDGE = clazz->getField<jni::JArrayClass<JPoint>>("NOSE_BRIDGE");
      jni::local_ref<jni::JArrayClass<JPoint>> NOSE_BRIDGE = this->getFieldValue(fieldNOSE_BRIDGE);
      static const auto fieldNOSE_BOTTOM = clazz->getField<jni::JArrayClass<JPoint>>("NOSE_BOTTOM");
      jni::local_ref<jni::JArrayClass<JPoint>> NOSE_BOTTOM = this->getFieldValue(fieldNOSE_BOTTOM);
      static const auto fieldLEFT_CHEEK = clazz->getField<jni::JArrayClass<JPoint>>("LEFT_CHEEK");
      jni::local_ref<jni::JArrayClass<JPoint>> LEFT_CHEEK = this->getFieldValue(fieldLEFT_CHEEK);
      static const auto fieldRIGHT_CHEEK = clazz->getField<jni::JArrayClass<JPoint>>("RIGHT_CHEEK");
      jni::local_ref<jni::JArrayClass<JPoint>> RIGHT_CHEEK = this->getFieldValue(fieldRIGHT_CHEEK);
      return Contours(
        FACE != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(FACE)) : std::nullopt,
        LEFT_EYEBROW_TOP != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LEFT_EYEBROW_TOP)) : std::nullopt,
        LEFT_EYEBROW_BOTTOM != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LEFT_EYEBROW_BOTTOM)) : std::nullopt,
        RIGHT_EYEBROW_TOP != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(RIGHT_EYEBROW_TOP)) : std::nullopt,
        RIGHT_EYEBROW_BOTTOM != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(RIGHT_EYEBROW_BOTTOM)) : std::nullopt,
        LEFT_EYE != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LEFT_EYE)) : std::nullopt,
        RIGHT_EYE != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(RIGHT_EYE)) : std::nullopt,
        UPPER_LIP_TOP != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(UPPER_LIP_TOP)) : std::nullopt,
        UPPER_LIP_BOTTOM != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(UPPER_LIP_BOTTOM)) : std::nullopt,
        LOWER_LIP_TOP != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LOWER_LIP_TOP)) : std::nullopt,
        LOWER_LIP_BOTTOM != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LOWER_LIP_BOTTOM)) : std::nullopt,
        NOSE_BRIDGE != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(NOSE_BRIDGE)) : std::nullopt,
        NOSE_BOTTOM != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(NOSE_BOTTOM)) : std::nullopt,
        LEFT_CHEEK != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(LEFT_CHEEK)) : std::nullopt,
        RIGHT_CHEEK != nullptr ? std::make_optional([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<Point> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(RIGHT_CHEEK)) : 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<JContours::javaobject> fromCpp(const Contours& value) {
      using JSignature = JContours(jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>, jni::alias_ref<jni::JArrayClass<JPoint>>);
      static const auto clazz = javaClassStatic();
      static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
      return create(
        clazz,
        value.FACE.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.FACE.value()) : nullptr,
        value.LEFT_EYEBROW_TOP.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LEFT_EYEBROW_TOP.value()) : nullptr,
        value.LEFT_EYEBROW_BOTTOM.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LEFT_EYEBROW_BOTTOM.value()) : nullptr,
        value.RIGHT_EYEBROW_TOP.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.RIGHT_EYEBROW_TOP.value()) : nullptr,
        value.RIGHT_EYEBROW_BOTTOM.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.RIGHT_EYEBROW_BOTTOM.value()) : nullptr,
        value.LEFT_EYE.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LEFT_EYE.value()) : nullptr,
        value.RIGHT_EYE.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.RIGHT_EYE.value()) : nullptr,
        value.UPPER_LIP_TOP.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.UPPER_LIP_TOP.value()) : nullptr,
        value.UPPER_LIP_BOTTOM.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.UPPER_LIP_BOTTOM.value()) : nullptr,
        value.LOWER_LIP_TOP.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LOWER_LIP_TOP.value()) : nullptr,
        value.LOWER_LIP_BOTTOM.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LOWER_LIP_BOTTOM.value()) : nullptr,
        value.NOSE_BRIDGE.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.NOSE_BRIDGE.value()) : nullptr,
        value.NOSE_BOTTOM.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.NOSE_BOTTOM.value()) : nullptr,
        value.LEFT_CHEEK.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.LEFT_CHEEK.value()) : nullptr,
        value.RIGHT_CHEEK.has_value() ? [&](auto&& __input) {
          size_t __size = __input.size();
          jni::local_ref<jni::JArrayClass<JPoint>> __array = jni::JArrayClass<JPoint>::newArray(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            const auto& __element = __input[__i];
            auto __elementJni = JPoint::fromCpp(__element);
            __array->setElement(__i, *__elementJni);
          }
          return __array;
        }(value.RIGHT_CHEEK.value()) : nullptr
      );
    }
  };

} // namespace margelo::nitro::camera::facedetector
