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

#include "HybridNitroVtoViewComponent.hpp"

#include <string>
#include <exception>
#include <utility>
#include <NitroModules/NitroDefines.hpp>
#include <NitroModules/JSIConverter.hpp>
#include <react/renderer/core/RawValue.h>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/core/ComponentDescriptor.h>
#include <react/renderer/components/view/ViewProps.h>

namespace margelo::nitro::nitrovto::views {

  extern const char HybridNitroVtoViewComponentName[] = "NitroVtoView";

  HybridNitroVtoViewProps::HybridNitroVtoViewProps(const react::PropsParserContext& context,
                                                   const HybridNitroVtoViewProps& sourceProps,
                                                   const react::RawProps& rawProps):
    react::ViewProps(context, sourceProps, rawProps, filterObjectKeys),
    modelUrl([&]() -> CachedProp<std::string> {
      try {
        const react::RawValue* rawValue = rawProps.at("modelUrl", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.modelUrl;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::string>::fromRawValue(*runtime, value, sourceProps.modelUrl);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.modelUrl: ") + exc.what());
      }
    }()),
    isActive([&]() -> CachedProp<bool> {
      try {
        const react::RawValue* rawValue = rawProps.at("isActive", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.isActive;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<bool>::fromRawValue(*runtime, value, sourceProps.isActive);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.isActive: ") + exc.what());
      }
    }()),
    onModelLoaded([&]() -> CachedProp<std::optional<std::function<void(const std::string& /* modelUrl */)>>> {
      try {
        const react::RawValue* rawValue = rawProps.at("onModelLoaded", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.onModelLoaded;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<std::function<void(const std::string& /* modelUrl */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, "f"), sourceProps.onModelLoaded);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.onModelLoaded: ") + exc.what());
      }
    }()),
    onFaceTracked([&]() -> CachedProp<std::optional<std::function<void()>>> {
      try {
        const react::RawValue* rawValue = rawProps.at("onFaceTracked", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.onFaceTracked;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<std::function<void()>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, "f"), sourceProps.onFaceTracked);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.onFaceTracked: ") + exc.what());
      }
    }()),
    onGlassesDisplayed([&]() -> CachedProp<std::optional<std::function<void(const std::string& /* modelUrl */)>>> {
      try {
        const react::RawValue* rawValue = rawProps.at("onGlassesDisplayed", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.onGlassesDisplayed;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<std::function<void(const std::string& /* modelUrl */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, "f"), sourceProps.onGlassesDisplayed);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.onGlassesDisplayed: ") + exc.what());
      }
    }()),
    forwardOffset([&]() -> CachedProp<std::optional<double>> {
      try {
        const react::RawValue* rawValue = rawProps.at("forwardOffset", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.forwardOffset;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.forwardOffset);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.forwardOffset: ") + exc.what());
      }
    }()),
    debug([&]() -> CachedProp<std::optional<bool>> {
      try {
        const react::RawValue* rawValue = rawProps.at("debug", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.debug;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<bool>>::fromRawValue(*runtime, value, sourceProps.debug);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.debug: ") + exc.what());
      }
    }()),
    showNativeFPS([&]() -> CachedProp<std::optional<bool>> {
      try {
        const react::RawValue* rawValue = rawProps.at("showNativeFPS", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.showNativeFPS;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<bool>>::fromRawValue(*runtime, value, sourceProps.showNativeFPS);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.showNativeFPS: ") + exc.what());
      }
    }()),
    isClipOn([&]() -> CachedProp<bool> {
      try {
        const react::RawValue* rawValue = rawProps.at("isClipOn", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.isClipOn;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<bool>::fromRawValue(*runtime, value, sourceProps.isClipOn);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.isClipOn: ") + exc.what());
      }
    }()),
    hybridRef([&]() -> CachedProp<std::optional<std::function<void(const std::shared_ptr<HybridNitroVtoViewSpec>& /* ref */)>>> {
      try {
        const react::RawValue* rawValue = rawProps.at("hybridRef", nullptr, nullptr);
        if (rawValue == nullptr) return sourceProps.hybridRef;
        const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
        return CachedProp<std::optional<std::function<void(const std::shared_ptr<HybridNitroVtoViewSpec>& /* ref */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, "f"), sourceProps.hybridRef);
      } catch (const std::exception& exc) {
        throw std::runtime_error(std::string("NitroVtoView.hybridRef: ") + exc.what());
      }
    }()) { }

  HybridNitroVtoViewProps::HybridNitroVtoViewProps(const HybridNitroVtoViewProps& other):
    react::ViewProps(),
    modelUrl(other.modelUrl),
    isActive(other.isActive),
    onModelLoaded(other.onModelLoaded),
    onFaceTracked(other.onFaceTracked),
    onGlassesDisplayed(other.onGlassesDisplayed),
    forwardOffset(other.forwardOffset),
    debug(other.debug),
    showNativeFPS(other.showNativeFPS),
    isClipOn(other.isClipOn),
    hybridRef(other.hybridRef) { }

  bool HybridNitroVtoViewProps::filterObjectKeys(const std::string& propName) {
    switch (hashString(propName)) {
      case hashString("modelUrl"): return true;
      case hashString("isActive"): return true;
      case hashString("onModelLoaded"): return true;
      case hashString("onFaceTracked"): return true;
      case hashString("onGlassesDisplayed"): return true;
      case hashString("forwardOffset"): return true;
      case hashString("debug"): return true;
      case hashString("showNativeFPS"): return true;
      case hashString("isClipOn"): return true;
      case hashString("hybridRef"): return true;
      default: return false;
    }
  }

  HybridNitroVtoViewComponentDescriptor::HybridNitroVtoViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters)
    : ConcreteComponentDescriptor(parameters,
                                  react::RawPropsParser(/* enableJsiParser */ true)) {}

  std::shared_ptr<const react::Props> HybridNitroVtoViewComponentDescriptor::cloneProps(const react::PropsParserContext& context,
                                                                                        const std::shared_ptr<const react::Props>& props,
                                                                                        react::RawProps rawProps) const {
    // 1. Prepare raw props parser
    rawProps.parse(rawPropsParser_);
    // 2. Copy props with Nitro's cached copy constructor
    return HybridNitroVtoViewShadowNode::Props(context, /* & */ rawProps, props);
  }

#ifdef ANDROID
  void HybridNitroVtoViewComponentDescriptor::adopt(react::ShadowNode& shadowNode) const {
    // This is called immediately after `ShadowNode` is created, cloned or in progress.
    // On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++.
    auto& concreteShadowNode = dynamic_cast<HybridNitroVtoViewShadowNode&>(shadowNode);
    const HybridNitroVtoViewProps& props = concreteShadowNode.getConcreteProps();
    HybridNitroVtoViewState state;
    state.setProps(props);
    concreteShadowNode.setStateData(std::move(state));
  }
#endif

} // namespace margelo::nitro::nitrovto::views
