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

#include "JHybridMailMailboxSpec.hpp"

// Forward declaration of `MailHeaderStruct` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailHeaderStruct; }
// Forward declaration of `MailAddressStruct` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailAddressStruct; }
// Forward declaration of `MailMessageStruct` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailMessageStruct; }
// Forward declaration of `MailAttachmentStruct` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailAttachmentStruct; }
// Forward declaration of `MailFetchHeadersOptions` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailFetchHeadersOptions; }
// Forward declaration of `MailFetchMessageOptions` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailFetchMessageOptions; }
// Forward declaration of `MailSearchCriteria` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailSearchCriteria; }
// Forward declaration of `MailNewMailEvent` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailNewMailEvent; }
// Forward declaration of `MailErrorStruct` to properly resolve imports.
namespace margelo::nitro::mailengine { struct MailErrorStruct; }

#include <string>
#include "MailHeaderStruct.hpp"
#include <vector>
#include <NitroModules/Promise.hpp>
#include <NitroModules/JPromise.hpp>
#include "JMailHeaderStruct.hpp"
#include <optional>
#include "MailAddressStruct.hpp"
#include "JMailAddressStruct.hpp"
#include "MailMessageStruct.hpp"
#include "JMailMessageStruct.hpp"
#include "MailAttachmentStruct.hpp"
#include "JMailAttachmentStruct.hpp"
#include <NitroModules/ArrayBuffer.hpp>
#include <NitroModules/JArrayBuffer.hpp>
#include <NitroModules/JUnit.hpp>
#include "MailFetchHeadersOptions.hpp"
#include "JMailFetchHeadersOptions.hpp"
#include "MailFetchMessageOptions.hpp"
#include "JMailFetchMessageOptions.hpp"
#include "MailSearchCriteria.hpp"
#include "JMailSearchCriteria.hpp"
#include "MailNewMailEvent.hpp"
#include <functional>
#include "JFunc_void_MailNewMailEvent.hpp"
#include <NitroModules/JNICallable.hpp>
#include "JMailNewMailEvent.hpp"
#include "MailErrorStruct.hpp"
#include "JFunc_void_MailErrorStruct.hpp"
#include "JMailErrorStruct.hpp"

namespace margelo::nitro::mailengine {

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

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

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

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

  // Properties
  std::string JHybridMailMailboxSpec::getPath() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getPath");
    auto __result = method(_javaPart);
    return __result->toStdString();
  }
  double JHybridMailMailboxSpec::getExists() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>("getExists");
    auto __result = method(_javaPart);
    return __result;
  }
  double JHybridMailMailboxSpec::getUnseen() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>("getUnseen");
    auto __result = method(_javaPart);
    return __result;
  }
  double JHybridMailMailboxSpec::getUidNext() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>("getUidNext");
    auto __result = method(_javaPart);
    return __result;
  }
  double JHybridMailMailboxSpec::getUidValidity() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>("getUidValidity");
    auto __result = method(_javaPart);
    return __result;
  }

  // Methods
  std::shared_ptr<Promise<std::vector<MailHeaderStruct>>> JHybridMailMailboxSpec::fetchHeaders(const MailFetchHeadersOptions& options) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JMailFetchHeadersOptions> /* options */)>("fetchHeaders");
    auto __result = method(_javaPart, JMailFetchHeadersOptions::fromCpp(options));
    return [&]() {
      auto __promise = Promise<std::vector<MailHeaderStruct>>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
        auto __result = jni::static_ref_cast<jni::JArrayClass<JMailHeaderStruct>>(__boxedResult);
        __promise->resolve([&](auto&& __input) {
          size_t __size = __input->size();
          std::vector<MailHeaderStruct> __vector;
          __vector.reserve(__size);
          for (size_t __i = 0; __i < __size; __i++) {
            auto __element = __input->getElement(__i);
            __vector.push_back(__element->toCpp());
          }
          return __vector;
        }(__result));
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<MailMessageStruct>> JHybridMailMailboxSpec::fetchMessage(double uid, const MailFetchMessageOptions& options) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(double /* uid */, jni::alias_ref<JMailFetchMessageOptions> /* options */)>("fetchMessage");
    auto __result = method(_javaPart, uid, JMailFetchMessageOptions::fromCpp(options));
    return [&]() {
      auto __promise = Promise<MailMessageStruct>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
        auto __result = jni::static_ref_cast<JMailMessageStruct>(__boxedResult);
        __promise->resolve(__result->toCpp());
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> JHybridMailMailboxSpec::fetchAttachment(double uid, const std::string& partId) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(double /* uid */, jni::alias_ref<jni::JString> /* partId */)>("fetchAttachment");
    auto __result = method(_javaPart, uid, jni::make_jstring(partId));
    return [&]() {
      auto __promise = Promise<std::shared_ptr<ArrayBuffer>>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
        auto __result = jni::static_ref_cast<JArrayBuffer::javaobject>(__boxedResult);
        __promise->resolve(__result->cthis()->getArrayBuffer());
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<std::vector<double>>> JHybridMailMailboxSpec::search(const MailSearchCriteria& criteria) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JMailSearchCriteria> /* criteria */)>("search");
    auto __result = method(_javaPart, JMailSearchCriteria::fromCpp(criteria));
    return [&]() {
      auto __promise = Promise<std::vector<double>>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
        auto __result = jni::static_ref_cast<jni::JArrayDouble>(__boxedResult);
        __promise->resolve([&]() {
          size_t __size = __result->size();
          std::vector<double> __vector(__size);
          __result->getRegion(0, __size, __vector.data());
          return __vector;
        }());
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::addFlags(const std::vector<double>& uids, const std::vector<std::string>& flags) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jni::alias_ref<jni::JArrayClass<jni::JString>> /* flags */)>("addFlags");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), [&](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;
    }(flags));
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::removeFlags(const std::vector<double>& uids, const std::vector<std::string>& flags) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jni::alias_ref<jni::JArrayClass<jni::JString>> /* flags */)>("removeFlags");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), [&](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;
    }(flags));
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::markSeen(const std::vector<double>& uids, bool seen) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jboolean /* seen */)>("markSeen");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), seen);
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::moveMessages(const std::vector<double>& uids, const std::string& destinationPath) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jni::alias_ref<jni::JString> /* destinationPath */)>("moveMessages");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), jni::make_jstring(destinationPath));
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::copyMessages(const std::vector<double>& uids, const std::string& destinationPath) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jni::alias_ref<jni::JString> /* destinationPath */)>("copyMessages");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), jni::make_jstring(destinationPath));
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::deleteMessages(const std::vector<double>& uids, bool expunge) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JArrayDouble> /* uids */, jboolean /* expunge */)>("deleteMessages");
    auto __result = method(_javaPart, [&]() {
      size_t __size = uids.size();
      jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
      __array->setRegion(0, __size, uids.data());
      return __array;
    }(), expunge);
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::startIdle(const std::function<void(const MailNewMailEvent& /* event */)>& onMail, const std::function<void(const MailErrorStruct& /* error */)>& onError) {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JFunc_void_MailNewMailEvent::javaobject> /* onMail */, jni::alias_ref<JFunc_void_MailErrorStruct::javaobject> /* onError */)>("startIdle_cxx");
    auto __result = method(_javaPart, JFunc_void_MailNewMailEvent_cxx::fromCpp(onMail), JFunc_void_MailErrorStruct_cxx::fromCpp(onError));
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::stopIdle() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("stopIdle");
    auto __result = method(_javaPart);
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }
  std::shared_ptr<Promise<void>> JHybridMailMailboxSpec::close() {
    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("close");
    auto __result = method(_javaPart);
    return [&]() {
      auto __promise = Promise<void>::create();
      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
        __promise->resolve();
      });
      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
        jni::JniException __jniError(__throwable);
        __promise->reject(std::make_exception_ptr(__jniError));
      });
      return __promise;
    }();
  }

} // namespace margelo::nitro::mailengine
