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

#include "JHybridReadiumViewStateUpdater.hpp"
#include "views/HybridReadiumViewComponent.hpp"
#include <NitroModules/NitroDefines.hpp>
#include <react/fabric/StateWrapperImpl.h>

namespace margelo::nitro::readium::views {

using namespace facebook;
using ConcreteStateData = react::ConcreteState<HybridReadiumViewState>;

void JHybridReadiumViewStateUpdater::updateViewProps(jni::alias_ref<jni::JClass> /* class */,
                                           jni::alias_ref<JHybridReadiumViewSpec::JavaPart> javaView,
                                           jni::alias_ref<JStateWrapper::javaobject> stateWrapperInterface) {
  std::shared_ptr<JHybridReadiumViewSpec> hybridView = javaView->getJHybridReadiumViewSpec();

  // Get concrete StateWrapperImpl from passed StateWrapper interface object
  jobject rawStateWrapper = stateWrapperInterface.get();
  if (!stateWrapperInterface->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] {
      throw std::runtime_error("StateWrapper is not a StateWrapperImpl");
  }
  auto stateWrapper = jni::alias_ref<react::StateWrapperImpl::javaobject>{
            static_cast<react::StateWrapperImpl::javaobject>(rawStateWrapper)};
  std::shared_ptr<const react::State> state = stateWrapper->cthis()->getState();
  auto concreteState = std::static_pointer_cast<const ConcreteStateData>(state);
  const HybridReadiumViewState& data = concreteState->getData();
  const std::shared_ptr<HybridReadiumViewProps>& props = data.getProps();
  if (props == nullptr) [[unlikely]] {
    // Props aren't set yet!
    throw std::runtime_error("HybridReadiumViewState's data doesn't contain any props!");
  }

  // Update all props if they are dirty
  if (props->file.isDirty) {
    hybridView->setFile(props->file.value);
    props->file.isDirty = false;
  }
  if (props->preferences.isDirty) {
    hybridView->setPreferences(props->preferences.value);
    props->preferences.isDirty = false;
  }
  if (props->decorations.isDirty) {
    hybridView->setDecorations(props->decorations.value);
    props->decorations.isDirty = false;
  }
  if (props->selectionActions.isDirty) {
    hybridView->setSelectionActions(props->selectionActions.value);
    props->selectionActions.isDirty = false;
  }
  if (props->onLocationChange.isDirty) {
    hybridView->setOnLocationChange(props->onLocationChange.value);
    props->onLocationChange.isDirty = false;
  }
  if (props->onPublicationReady.isDirty) {
    hybridView->setOnPublicationReady(props->onPublicationReady.value);
    props->onPublicationReady.isDirty = false;
  }
  if (props->onDecorationActivated.isDirty) {
    hybridView->setOnDecorationActivated(props->onDecorationActivated.value);
    props->onDecorationActivated.isDirty = false;
  }
  if (props->onSelectionChange.isDirty) {
    hybridView->setOnSelectionChange(props->onSelectionChange.value);
    props->onSelectionChange.isDirty = false;
  }
  if (props->onSelectionAction.isDirty) {
    hybridView->setOnSelectionAction(props->onSelectionAction.value);
    props->onSelectionAction.isDirty = false;
  }

  // Update hybridRef if it changed
  if (props->hybridRef.isDirty) {
    // hybridRef changed - call it with new this
    const auto& maybeFunc = props->hybridRef.value;
    if (maybeFunc.has_value()) {
      maybeFunc.value()(hybridView);
    }
    props->hybridRef.isDirty = false;
  }
}

} // namespace margelo::nitro::readium::views
