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

#import "HybridVideoViewComponent.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 "HybridVideoViewSpecSwift.hpp"
#import "Aviation-Swift-Cxx-Umbrella.hpp"

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

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

@implementation HybridVideoViewComponent {
  std::shared_ptr<HybridVideoViewSpecSwift> _hybridView;
}

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

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

- (instancetype) init {
  if (self = [super init]) {
    std::shared_ptr<HybridVideoViewSpec> hybridView = Aviation::AviationAutolinking::createVideoView();
    _hybridView = std::dynamic_pointer_cast<HybridVideoViewSpecSwift>(hybridView);
    [self updateView];
  }
  return self;
}

- (void) updateView {
  // 1. Get Swift part
  Aviation::HybridVideoViewSpec_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<HybridVideoViewProps const>(props);
  auto& newViewProps = const_cast<HybridVideoViewProps&>(newViewPropsConst);
  Aviation::HybridVideoViewSpec_cxx& swiftPart = _hybridView->getSwiftPart();

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

  // resizeMode: enum
  if (newViewProps.resizeMode.isDirty) {
    swiftPart.setResizeMode(static_cast<int>(newViewProps.resizeMode.value));
    newViewProps.resizeMode.isDirty = false;
  }
  // pipEnabled: boolean
  if (newViewProps.pipEnabled.isDirty) {
    swiftPart.setPipEnabled(newViewProps.pipEnabled.value);
    newViewProps.pipEnabled.isDirty = false;
  }
  // playInBackground: boolean
  if (newViewProps.playInBackground.isDirty) {
    swiftPart.setPlayInBackground(newViewProps.playInBackground.value);
    newViewProps.playInBackground.isDirty = false;
  }
  // onPipStart: function
  if (newViewProps.onPipStart.isDirty) {
    swiftPart.setOnPipStart(newViewProps.onPipStart.value);
    newViewProps.onPipStart.isDirty = false;
  }
  // onPipStop: function
  if (newViewProps.onPipStop.isDirty) {
    swiftPart.setOnPipStop(newViewProps.onPipStop.value);
    newViewProps.onPipStop.isDirty = false;
  }
  // surfaceType: enum
  if (newViewProps.surfaceType.isDirty) {
    swiftPart.setSurfaceType(static_cast<int>(newViewProps.surfaceType.value));
    newViewProps.surfaceType.isDirty = false;
  }
  // onFullscreenEnter: function
  if (newViewProps.onFullscreenEnter.isDirty) {
    swiftPart.setOnFullscreenEnter(newViewProps.onFullscreenEnter.value);
    newViewProps.onFullscreenEnter.isDirty = false;
  }
  // onFullscreenExit: function
  if (newViewProps.onFullscreenExit.isDirty) {
    swiftPart.setOnFullscreenExit(newViewProps.onFullscreenExit.value);
    newViewProps.onFullscreenExit.isDirty = false;
  }
  // selectedVideoTrack: struct
  if (newViewProps.selectedVideoTrack.isDirty) {
    swiftPart.setSelectedVideoTrack(newViewProps.selectedVideoTrack.value);
    newViewProps.selectedVideoTrack.isDirty = false;
  }
  // selectedSubtitleTrack: struct
  if (newViewProps.selectedSubtitleTrack.isDirty) {
    swiftPart.setSelectedSubtitleTrack(newViewProps.selectedSubtitleTrack.value);
    newViewProps.selectedSubtitleTrack.isDirty = false;
  }
  // selectedAudioTrack: struct
  if (newViewProps.selectedAudioTrack.isDirty) {
    swiftPart.setSelectedAudioTrack(newViewProps.selectedAudioTrack.value);
    newViewProps.selectedAudioTrack.isDirty = false;
  }
  // adTagUrl: string
  if (newViewProps.adTagUrl.isDirty) {
    swiftPart.setAdTagUrl(newViewProps.adTagUrl.value);
    newViewProps.adTagUrl.isDirty = false;
  }
  // source: struct
  if (newViewProps.source.isDirty) {
    swiftPart.setSource(newViewProps.source.value);
    newViewProps.source.isDirty = false;
  }
  // autoPlay: boolean
  if (newViewProps.autoPlay.isDirty) {
    swiftPart.setAutoPlay(newViewProps.autoPlay.value);
    newViewProps.autoPlay.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 Aviation::AviationAutolinking::isVideoViewRecyclable();
}

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

@end
