#ifdef RCT_NEW_ARCH_ENABLED
#import "RNScanbotDocumentScannerView.h"

#import <react/renderer/components/RNScanbotScannerViewSpec/ComponentDescriptors.h>
#import <react/renderer/components/RNScanbotScannerViewSpec/EventEmitters.h>
#import <react/renderer/components/RNScanbotScannerViewSpec/Props.h>
#import <react/renderer/components/RNScanbotScannerViewSpec/RCTComponentViewHelpers.h>

#import "RCTFabricComponentsPlugins.h"
#import <React/RCTConversions.h>

#if __has_include(<RNScanbotSDK/RNScanbotSDK-Swift.h>)
#import <RNScanbotSDK/RNScanbotSDK-Swift.h>
#else
#import "RNScanbotSDK-Swift.h"
#endif



using namespace facebook::react;

@interface RNScanbotDocumentScannerView()  <RCTScanbotDocumentScannerViewViewProtocol>
@property (strong, nonatomic) RNScanbotDocumentScannerLegacyView *view;
@end


@implementation RNScanbotDocumentScannerView

static const auto defaultProps = std::make_shared<const ScanbotDocumentScannerViewProps>();

+ (ComponentDescriptorProvider)componentDescriptorProvider {
  return concreteComponentDescriptorProvider<ScanbotDocumentScannerViewComponentDescriptor>();
}

- (instancetype)initWithFrame:(CGRect)frame {
  if (self = [super initWithFrame:frame]) {
    _props = defaultProps;
    self.view = [[RNScanbotDocumentScannerLegacyView alloc] initWithFrame:frame delegate:self];
    self.contentView = _view;
  }
  return self;
}

- (void) prepareForRecycle {
  self.contentView = [[UIView alloc] initWithFrame:self.view.frame];;
  self.view = nil;
  _props = defaultProps;
  [super prepareForRecycle];
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {

  if(self.view == nil){
    self.view = [[RNScanbotDocumentScannerLegacyView alloc] initWithFrame:self.contentView.frame delegate:self];
    self.contentView = _view;
  }

  const auto &oldViewProps = *std::static_pointer_cast<ScanbotDocumentScannerViewProps const>(_props);
  const auto &newViewProps = *std::static_pointer_cast<ScanbotDocumentScannerViewProps const>(props);

  if(oldViewProps.acceptedAngleScore != newViewProps.acceptedAngleScore){
    [self.view setAcceptedAngleScore: [NSNumber numberWithDouble:newViewProps.acceptedAngleScore]];
  }
  if(oldViewProps.acceptedBrightnessThreshold != newViewProps.acceptedBrightnessThreshold){
    [self.view setAcceptedBrightnessThreshold: [NSNumber numberWithDouble:newViewProps.acceptedBrightnessThreshold]];
  }
  if(oldViewProps.acceptedSizeScore != newViewProps.acceptedSizeScore){
    [self.view setAcceptedSizeScore: [NSNumber numberWithDouble:newViewProps.acceptedSizeScore]];
  }
  if(oldViewProps.autoSnappingEnabled != newViewProps.autoSnappingEnabled){
    [self.view setAutoSnappingEnabled:newViewProps.autoSnappingEnabled];
  }
  if(oldViewProps.autoSnappingSensitivity != newViewProps.autoSnappingSensitivity){
    [self.view setAutoSnappingSensitivity: [NSNumber numberWithDouble:newViewProps.autoSnappingSensitivity]];
  }
  if(oldViewProps.autoSnappingDelay != newViewProps.autoSnappingDelay){
    [self.view setAutoSnappingDelay: [NSNumber numberWithDouble:newViewProps.autoSnappingDelay]];
  }
  if(![self compareStringProps:oldViewProps.cameraModule withString:newViewProps.cameraModule]){
    [self.view setCameraModule: [self toNSString: newViewProps.cameraModule]];
  }
  if(![self compareStringProps:oldViewProps.cameraPreviewMode withString:newViewProps.cameraPreviewMode]){
    [self.view setCameraPreviewMode: [self toNSString: newViewProps.cameraPreviewMode]];
  }
  if(oldViewProps.flashEnabled != newViewProps.flashEnabled){
    [self.view setFlashEnabled: newViewProps.flashEnabled];
  }
  if(oldViewProps.ignoreOrientationMismatch != newViewProps.ignoreOrientationMismatch){
    [self.view setIgnoreOrientationMismatch: newViewProps.ignoreOrientationMismatch];
  }
  if(![self compareStringProps:oldViewProps.photoQualityPrioritization withString:newViewProps.photoQualityPrioritization]){
    [self.view setPhotoQualityPrioritization: [self toNSString:newViewProps.photoQualityPrioritization]];
  }
  if(oldViewProps.requiredAspectRatios != newViewProps.requiredAspectRatios){
    NSMutableArray *aspectRatios = [NSMutableArray array];
    for (ScanbotDocumentScannerViewRequiredAspectRatiosStruct value : newViewProps.requiredAspectRatios) {
      [aspectRatios addObject:@{
        @"width": [NSNumber numberWithDouble:value.width],
        @"height": [NSNumber numberWithDouble:value.height]
      }];
    }
    [self.view setRequiredAspectRatios:aspectRatios];
  }
  if(oldViewProps.finderEnabled != newViewProps.finderEnabled){
    [self.view setFinderEnabled:newViewProps.finderEnabled];
  }
  if(oldViewProps.finderLineColor != newViewProps.finderLineColor){
    [self.view setFinderLineColor: RCTUIColorFromSharedColor(newViewProps.finderLineColor)];
  }
  if(oldViewProps.finderLineWidth != newViewProps.finderLineWidth){
    [self.view setFinderLineWidth: [NSNumber numberWithDouble:newViewProps.finderLineWidth]];
  }
  if(oldViewProps.finderOverlayColor != newViewProps.finderOverlayColor){
    [self.view setFinderOverlayColor: RCTUIColorFromSharedColor(newViewProps.finderOverlayColor)];
  }
  if(oldViewProps.finderCornerRadius != newViewProps.finderCornerRadius){
    [self.view setFinderCornerRadius: [NSNumber numberWithDouble:newViewProps.finderCornerRadius]];
  }
  if(oldViewProps.finderMinimumPadding != newViewProps.finderMinimumPadding){
    [self.view setFinderMinimumPadding: [NSNumber numberWithDouble:newViewProps.finderMinimumPadding]];
  }
  if(oldViewProps.finderAspectRatio != newViewProps.finderAspectRatio){
    [self.view setFinderAspectRatio: @{
      @"width": [NSNumber numberWithDouble:newViewProps.finderAspectRatio.width],
      @"height": [NSNumber numberWithDouble:newViewProps.finderAspectRatio.height]
    }];
  }
  if(oldViewProps.polygonEnabled != newViewProps.polygonEnabled){
    [self.view setPolygonEnabled: newViewProps.polygonEnabled];
  }
  if(oldViewProps.polygonBackgroundColor != newViewProps.polygonBackgroundColor){
    [self.view setPolygonBackgroundColor: RCTUIColorFromSharedColor(newViewProps.polygonBackgroundColor)];
  }
  if(oldViewProps.polygonBackgroundColorOK != newViewProps.polygonBackgroundColorOK){
    [self.view setPolygonBackgroundColorOK: RCTUIColorFromSharedColor(newViewProps.polygonBackgroundColorOK)];
  }
  if(oldViewProps.polygonColor != newViewProps.polygonColor){
    [self.view setPolygonColor: RCTUIColorFromSharedColor(newViewProps.polygonColor)];
  }
  if(oldViewProps.polygonColorOK != newViewProps.polygonColorOK){
    [self.view setPolygonColorOK: RCTUIColorFromSharedColor(newViewProps.polygonColorOK)];
  }
  if(oldViewProps.polygonLineWidth != newViewProps.polygonLineWidth){
    [self.view setPolygonLineWidth: [NSNumber numberWithDouble:newViewProps.polygonLineWidth]];
  }
  if(oldViewProps.polygonCornerRadius != newViewProps.polygonCornerRadius){
    [self.view setPolygonCornerRadius: [NSNumber numberWithDouble: newViewProps.polygonCornerRadius]];
  }
  if(oldViewProps.polygonAutoSnapProgressColor != newViewProps.polygonAutoSnapProgressColor){
    [self.view setPolygonAutoSnapProgressColor: RCTUIColorFromSharedColor(newViewProps.polygonAutoSnapProgressColor)];
  }
  if(oldViewProps.polygonAutoSnapProgressLineWidth != newViewProps.polygonAutoSnapProgressLineWidth){
    [self.view setPolygonAutoSnapProgressLineWidth: [NSNumber numberWithDouble: newViewProps.polygonAutoSnapProgressLineWidth]];
  }
  if(oldViewProps.polygonAutoSnapProgressEnabled != newViewProps.polygonAutoSnapProgressEnabled){
    [self.view setPolygonAutoSnapProgressEnabled:newViewProps.polygonAutoSnapProgressEnabled];
  }
  if(oldViewProps.hardwareButtonsEnabled != newViewProps.hardwareButtonsEnabled){
    [self.view setHardwareButtonsEnabled:newViewProps.hardwareButtonsEnabled];
  }

  [super updateProps:props oldProps:oldProps];
}

- (void)handleCommand:(nonnull const NSString *)commandName
                 args:(nonnull const NSArray *)args {
  RCTScanbotDocumentScannerViewHandleCommand(self, commandName, args);
}

- (void)freezeCamera {
    [self.view freezeCamera];
}

- (void)unfreezeCamera {
    [self.view unfreezeCamera];
}

- (void)snapDocument:(BOOL)acquireFocus { 
    [self.view snapDocument];
}

- (void)documentScannerViewController:(SBSDKDocumentScannerViewController * _Nonnull)controller
                 didSnapDocumentImage:(UIImage * _Nonnull)documentImage
                              onImage:(UIImage * _Nonnull)originalImage
                           withResult:(SBSDKDocumentDetectionResult * _Nullable)result
                          autoSnapped:(BOOL)autoSnapped {
    if (_eventEmitter == nullptr) return;
    
    if (result == nil) return;
    
    NSString* _Nullable base64String = [self.view onDidDetectDocumentWithDocumentImage:documentImage];
    if(base64String != nil) {
        const auto &eventEmitter = std::dynamic_pointer_cast<const facebook::react::ScanbotDocumentScannerViewEventEmitter>(_eventEmitter);
        eventEmitter->onDocumentScannerResult(facebook::react::ScanbotDocumentScannerViewEventEmitter::OnDocumentScannerResult{.result = std::string([base64String UTF8String])});
    }
}

- (void)documentScannerViewController:(SBSDKDocumentScannerViewController *)controller
                  didSampleVideoFrame:(UIImage *)videoFrameImage
                       scanningResult:(SBSDKDocumentDetectionResult * _Nullable)result {
    if (_eventEmitter == nullptr) return;
    
    if (result == nil) return;
    
    NSString* _Nullable status = [self.view onDidDetectFrameWithResult:result];
    if(status != nil){
        const auto &eventEmitter = std::dynamic_pointer_cast<const facebook::react::ScanbotDocumentScannerViewEventEmitter>(_eventEmitter);
        eventEmitter->onDetectionResult(facebook::react::ScanbotDocumentScannerViewEventEmitter::OnDetectionResult{
            .result = std::string([status UTF8String])});
    }
}

bool operator!=(ScanbotDocumentScannerViewFinderAspectRatioStruct const &i,
                ScanbotDocumentScannerViewFinderAspectRatioStruct const &j){
    return !(i.width == j.width && i.height == j.height);
}

bool operator!=(ScanbotDocumentScannerViewRequiredAspectRatiosStruct const &i,
                ScanbotDocumentScannerViewRequiredAspectRatiosStruct const &j){
    return !(i.width == j.width && i.height == j.height);
}

bool operator!=(std::vector<ScanbotDocumentScannerViewRequiredAspectRatiosStruct> const &v1,
                std::vector<ScanbotDocumentScannerViewRequiredAspectRatiosStruct> const &v2){
    
    if(v1.size() != v2.size()) return true;
    
    for(int i = 0; i< v1.size(); i++){
        if(v1[i] != v2[i]){
            return true;
        }
    }
    
    return false;
}

- (NSString*) toNSString:(std::string) value {
    return [[NSString alloc] initWithCString:value.c_str() encoding:NSUTF8StringEncoding];
}

- (BOOL)compareStringProps:(std::string)oldProp withString:(std::string)newProp {
    return [[self toNSString:oldProp] isEqualToString: [self toNSString:newProp]];
}

Class <RCTComponentViewProtocol> ScanbotDocumentScannerViewCls(void){
    return RNScanbotDocumentScannerView.class;
}

@end

#endif
