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

#import "HybridParticleCanvasViewComponent.hpp"
#import <memory>
#import <react/renderer/componentregistry/ComponentDescriptorProvider.h>
#import <React/RCTViewComponentView.h>
#import <React/RCTComponentViewFactory.h>
#import <React/UIView+ComponentViewProtocol.h>
#import <NitroModules/NitroDefines.hpp>
#import <UIKit/UIKit.h>

#import "HybridParticleCanvasViewSpecSwift.hpp"
#import "Particle-Swift-Cxx-Umbrella.hpp"

#if __has_include(<cxxreact/ReactNativeVersion.h>)
#include <cxxreact/ReactNativeVersion.h>
#if REACT_NATIVE_VERSION_MINOR >= 82
#define ENABLE_RCT_COMPONENT_VIEW_INVALIDATE
#endif
#endif

using namespace facebook;
using namespace margelo::nitro::particle;
using namespace margelo::nitro::particle::views;

/**
 * Represents the React Native View holder for the Nitro "ParticleCanvasView" HybridView.
 */
@interface HybridParticleCanvasViewComponent: RCTViewComponentView
+ (BOOL)shouldBeRecycled;
@end

@implementation HybridParticleCanvasViewComponent {
  std::shared_ptr<HybridParticleCanvasViewSpecSwift> _hybridView;
}

+ (void) load {
  [super load];
  [RCTComponentViewFactory.currentComponentViewFactory registerComponentViewClass:[HybridParticleCanvasViewComponent class]];
}

+ (react::ComponentDescriptorProvider) componentDescriptorProvider {
  return react::concreteComponentDescriptorProvider<HybridParticleCanvasViewComponentDescriptor>();
}

- (instancetype) init {
  if (self = [super init]) {
    std::shared_ptr<HybridParticleCanvasViewSpec> hybridView = Particle::ParticleAutolinking::createParticleCanvasView();
    _hybridView = std::dynamic_pointer_cast<HybridParticleCanvasViewSpecSwift>(hybridView);
    [self updateView];
  }
  return self;
}

- (void) updateView {
  // 1. Get Swift part
  Particle::HybridParticleCanvasViewSpec_cxx& swiftPart = _hybridView->getSwiftPart();

  // 2. Get UIView*
  void* viewUnsafe = swiftPart.getView();
  UIView* view = (__bridge_transfer UIView*) viewUnsafe;

  // 3. Update RCTViewComponentView's [contentView]
  [self setContentView:view];
}

- (void) updateProps:(const std::shared_ptr<const react::Props>&)props
            oldProps:(const std::shared_ptr<const react::Props>&)oldProps {
  // 1. Downcast props
  const auto& newViewPropsConst = *std::static_pointer_cast<HybridParticleCanvasViewProps const>(props);
  auto& newViewProps = const_cast<HybridParticleCanvasViewProps&>(newViewPropsConst);
  Particle::HybridParticleCanvasViewSpec_cxx& swiftPart = _hybridView->getSwiftPart();

  // 2. Update each prop individually
  swiftPart.beforeUpdate();

  // preset: string
  if (newViewProps.preset.isDirty) {
    swiftPart.setPreset(newViewProps.preset.value);
    newViewProps.preset.isDirty = false;
  }
  // count: number
  if (newViewProps.count.isDirty) {
    swiftPart.setCount(newViewProps.count.value);
    newViewProps.count.isDirty = false;
  }
  // emitterX: number
  if (newViewProps.emitterX.isDirty) {
    swiftPart.setEmitterX(newViewProps.emitterX.value);
    newViewProps.emitterX.isDirty = false;
  }
  // emitterY: number
  if (newViewProps.emitterY.isDirty) {
    swiftPart.setEmitterY(newViewProps.emitterY.value);
    newViewProps.emitterY.isDirty = false;
  }
  // loop: boolean
  if (newViewProps.loop.isDirty) {
    swiftPart.setLoop(newViewProps.loop.value);
    newViewProps.loop.isDirty = false;
  }
  // emitInterval: number
  if (newViewProps.emitInterval.isDirty) {
    swiftPart.setEmitInterval(newViewProps.emitInterval.value);
    newViewProps.emitInterval.isDirty = false;
  }

  swiftPart.afterUpdate();

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

  // 4. Continue in base class
  [super updateProps:props oldProps:oldProps];
}

+ (BOOL)shouldBeRecycled {
  return Particle::ParticleAutolinking::isParticleCanvasViewRecyclable();
}

- (void)prepareForRecycle {
  [super prepareForRecycle];
  Particle::HybridParticleCanvasViewSpec_cxx& swiftPart = _hybridView->getSwiftPart();
  swiftPart.maybePrepareForRecycle();
}

#ifdef ENABLE_RCT_COMPONENT_VIEW_INVALIDATE
- (void)invalidate {
  Particle::HybridParticleCanvasViewSpec_cxx& swiftPart = _hybridView->getSwiftPart();
  swiftPart.onDropView();
  [super invalidate];
}
#endif

@end
