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

#include "JHybridPreviewViewSpec.hpp"

// Forward declaration of `HybridCameraPreviewOutputSpec` to properly resolve imports.
namespace margelo::nitro::camera { class HybridCameraPreviewOutputSpec; }
// Forward declaration of `PreviewResizeMode` to properly resolve imports.
namespace margelo::nitro::camera { enum class PreviewResizeMode; }
// Forward declaration of `PreviewImplementationMode` to properly resolve imports.
namespace margelo::nitro::camera { enum class PreviewImplementationMode; }
// Forward declaration of `HybridGestureControllerSpec` to properly resolve imports.
namespace margelo::nitro::camera { class HybridGestureControllerSpec; }
// Forward declaration of `HybridMeteringPointSpec` to properly resolve imports.
namespace margelo::nitro::camera { class HybridMeteringPointSpec; }
// Forward declaration of `HybridImageSpec` to properly resolve imports.
namespace margelo::nitro::image { class HybridImageSpec; }
// Forward declaration of `Point` to properly resolve imports.
namespace margelo::nitro::camera { struct Point; }
// Forward declaration of `HybridScannedObjectSpec` to properly resolve imports.
namespace margelo::nitro::camera { class HybridScannedObjectSpec; }

#include <memory>
#include "HybridCameraPreviewOutputSpec.hpp"
#include <optional>
#include "JHybridCameraPreviewOutputSpec.hpp"
#include "PreviewResizeMode.hpp"
#include "JPreviewResizeMode.hpp"
#include "PreviewImplementationMode.hpp"
#include "JPreviewImplementationMode.hpp"
#include "HybridGestureControllerSpec.hpp"
#include <vector>
#include "JHybridGestureControllerSpec.hpp"
#include <functional>
#include "JFunc_void.hpp"
#include <NitroModules/JNICallable.hpp>
#include "HybridMeteringPointSpec.hpp"
#include "JHybridMeteringPointSpec.hpp"
#include <NitroImage/HybridImageSpec.hpp>
#include <NitroModules/Promise.hpp>
#include <NitroModules/JPromise.hpp>
#include <NitroImage/JHybridImageSpec.hpp>
#include "Point.hpp"
#include "JPoint.hpp"
#include "HybridScannedObjectSpec.hpp"
#include "JHybridScannedObjectSpec.hpp"

namespace margelo::nitro::camera {

  std::shared_ptr<JHybridPreviewViewSpec> JHybridPreviewViewSpec::JavaPart::getJHybridPreviewViewSpec() {
    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();
    auto castHybridObject = std::dynamic_pointer_cast<JHybridPreviewViewSpec>(hybridObject);
    if (castHybridObject == nullptr) [[unlikely]] {
      throw std::runtime_error("Failed to downcast JHybridObject to JHybridPreviewViewSpec!");
    }
    return castHybridObject;
  }

  jni::local_ref<JHybridPreviewViewSpec::CxxPart::jhybriddata> JHybridPreviewViewSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {
    return makeCxxInstance(jThis);
  }

  std::shared_ptr<JHybridObject> JHybridPreviewViewSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {
    auto castJavaPart = jni::dynamic_ref_cast<JHybridPreviewViewSpec::JavaPart>(javaPart);
    if (castJavaPart == nullptr) [[unlikely]] {
      throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridPreviewViewSpec::JavaPart!");
    }
    return std::make_shared<JHybridPreviewViewSpec>(castJavaPart);
  }

  void JHybridPreviewViewSpec::CxxPart::registerNatives() {
    registerHybrid({
      makeNativeMethod("initHybrid", JHybridPreviewViewSpec::CxxPart::initHybrid),
    });
  }

  // Properties
  std::optional<std::shared_ptr<HybridCameraPreviewOutputSpec>> JHybridPreviewViewSpec::getPreviewOutput() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridCameraPreviewOutputSpec::JavaPart>()>("getPreviewOutput");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional(__result->getJHybridCameraPreviewOutputSpec()) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setPreviewOutput(const std::optional<std::shared_ptr<HybridCameraPreviewOutputSpec>>& previewOutput) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JHybridCameraPreviewOutputSpec::JavaPart> /* previewOutput */)>("setPreviewOutput");
    method(_javaPart, previewOutput.has_value() ? std::dynamic_pointer_cast<JHybridCameraPreviewOutputSpec>(previewOutput.value())->getJavaPart() : nullptr);
  }
  std::optional<PreviewResizeMode> JHybridPreviewViewSpec::getResizeMode() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPreviewResizeMode>()>("getResizeMode");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional(__result->toCpp()) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setResizeMode(std::optional<PreviewResizeMode> resizeMode) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JPreviewResizeMode> /* resizeMode */)>("setResizeMode");
    method(_javaPart, resizeMode.has_value() ? JPreviewResizeMode::fromCpp(resizeMode.value()) : nullptr);
  }
  std::optional<PreviewImplementationMode> JHybridPreviewViewSpec::getImplementationMode() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPreviewImplementationMode>()>("getImplementationMode");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional(__result->toCpp()) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setImplementationMode(std::optional<PreviewImplementationMode> implementationMode) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JPreviewImplementationMode> /* implementationMode */)>("setImplementationMode");
    method(_javaPart, implementationMode.has_value() ? JPreviewImplementationMode::fromCpp(implementationMode.value()) : nullptr);
  }
  std::optional<std::vector<std::shared_ptr<HybridGestureControllerSpec>>> JHybridPreviewViewSpec::getGestureControllers() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JArrayClass<JHybridGestureControllerSpec::JavaPart>>()>("getGestureControllers");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional([&](auto&& __input) {
      size_t __size = __input->size();
      std::vector<std::shared_ptr<HybridGestureControllerSpec>> __vector;
      __vector.reserve(__size);
      for (size_t __i = 0; __i < __size; __i++) {
        auto __element = __input->getElement(__i);
        __vector.push_back(__element->getJHybridGestureControllerSpec());
      }
      return __vector;
    }(__result)) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setGestureControllers(const std::optional<std::vector<std::shared_ptr<HybridGestureControllerSpec>>>& gestureControllers) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JArrayClass<JHybridGestureControllerSpec::JavaPart>> /* gestureControllers */)>("setGestureControllers");
    method(_javaPart, gestureControllers.has_value() ? [&](auto&& __input) {
      size_t __size = __input.size();
      jni::local_ref<jni::JArrayClass<JHybridGestureControllerSpec::JavaPart>> __array = jni::JArrayClass<JHybridGestureControllerSpec::JavaPart>::newArray(__size);
      for (size_t __i = 0; __i < __size; __i++) {
        const auto& __element = __input[__i];
        auto __elementJni = std::dynamic_pointer_cast<JHybridGestureControllerSpec>(__element)->getJavaPart();
        __array->setElement(__i, *__elementJni);
      }
      return __array;
    }(gestureControllers.value()) : nullptr);
  }
  std::optional<std::function<void()>> JHybridPreviewViewSpec::getOnPreviewStarted() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_void::javaobject>()>("getOnPreviewStarted_cxx");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional([&]() -> std::function<void()> {
      if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] {
        auto downcast = jni::static_ref_cast<JFunc_void_cxx::javaobject>(__result);
        return downcast->cthis()->getFunction();
      } else {
        auto __resultRef = jni::make_global(__result);
        return JNICallable<JFunc_void, void()>(std::move(__resultRef));
      }
    }()) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setOnPreviewStarted(const std::optional<std::function<void()>>& onPreviewStarted) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JFunc_void::javaobject> /* onPreviewStarted */)>("setOnPreviewStarted_cxx");
    method(_javaPart, onPreviewStarted.has_value() ? JFunc_void_cxx::fromCpp(onPreviewStarted.value()) : nullptr);
  }
  std::optional<std::function<void()>> JHybridPreviewViewSpec::getOnPreviewStopped() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_void::javaobject>()>("getOnPreviewStopped_cxx");
    auto __result = method(_javaPart);
    return __result != nullptr ? std::make_optional([&]() -> std::function<void()> {
      if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] {
        auto downcast = jni::static_ref_cast<JFunc_void_cxx::javaobject>(__result);
        return downcast->cthis()->getFunction();
      } else {
        auto __resultRef = jni::make_global(__result);
        return JNICallable<JFunc_void, void()>(std::move(__resultRef));
      }
    }()) : std::nullopt;
  }
  void JHybridPreviewViewSpec::setOnPreviewStopped(const std::optional<std::function<void()>>& onPreviewStopped) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JFunc_void::javaobject> /* onPreviewStopped */)>("setOnPreviewStopped_cxx");
    method(_javaPart, onPreviewStopped.has_value() ? JFunc_void_cxx::fromCpp(onPreviewStopped.value()) : nullptr);
  }

  // Methods
  std::shared_ptr<HybridMeteringPointSpec> JHybridPreviewViewSpec::createMeteringPoint(double viewX, double viewY, std::optional<double> size) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridMeteringPointSpec::JavaPart>(double /* viewX */, double /* viewY */, jni::alias_ref<jni::JDouble> /* size */)>("createMeteringPoint");
    auto __result = method(_javaPart, viewX, viewY, size.has_value() ? jni::JDouble::valueOf(size.value()) : nullptr);
    return __result->getJHybridMeteringPointSpec();
  }
  std::shared_ptr<Promise<std::shared_ptr<margelo::nitro::image::HybridImageSpec>>> JHybridPreviewViewSpec::takeSnapshot() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("takeSnapshot");
    auto __result = method(_javaPart);
    return [&]() {
      auto __promise = Promise<std::shared_ptr<margelo::nitro::image::HybridImageSpec>>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
        auto __result = jni::static_ref_cast<margelo::nitro::image::JHybridImageSpec::JavaPart>(__boxedResult);
        __promise->resolve(__result->getJHybridImageSpec());
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  Point JHybridPreviewViewSpec::convertCameraPointToViewPoint(const Point& cameraPoint) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPoint>(jni::alias_ref<JPoint> /* cameraPoint */)>("convertCameraPointToViewPoint");
    auto __result = method(_javaPart, JPoint::fromCpp(cameraPoint));
    return __result->toCpp();
  }
  Point JHybridPreviewViewSpec::convertViewPointToCameraPoint(const Point& viewPoint) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPoint>(jni::alias_ref<JPoint> /* viewPoint */)>("convertViewPointToCameraPoint");
    auto __result = method(_javaPart, JPoint::fromCpp(viewPoint));
    return __result->toCpp();
  }
  std::shared_ptr<HybridScannedObjectSpec> JHybridPreviewViewSpec::convertScannedObjectCoordinatesToViewCoordinates(const std::shared_ptr<HybridScannedObjectSpec>& scannedObject) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridScannedObjectSpec::JavaPart>(jni::alias_ref<JHybridScannedObjectSpec::JavaPart> /* scannedObject */)>("convertScannedObjectCoordinatesToViewCoordinates");
    auto __result = method(_javaPart, std::dynamic_pointer_cast<JHybridScannedObjectSpec>(scannedObject)->getJavaPart());
    return __result->getJHybridScannedObjectSpec();
  }

} // namespace margelo::nitro::camera
