
#ifdef RCT_NEW_ARCH_ENABLED
#import "RNScanbotBarcodeScannerView.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>

using namespace facebook::react;

@interface RNScanbotBarcodeScannerView() <RCTScanbotBarcodeScannerViewViewProtocol>
@property (strong, nonatomic) SBSDKBarcodeScannerViewController *scannerViewController;
@property (nonatomic) BOOL scanningEnabled;
@property (nonatomic) BOOL attached;
@property (nonatomic) NSString* _Nullable barcodeItemOverlayViewLoadingText;
@property (atomic) NSMutableDictionary* _Nullable barcodeItemOverlayViewBinders;
@end

@implementation RNScanbotBarcodeScannerView

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

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        static const auto defaultProps = std::make_shared<const ScanbotBarcodeScannerViewProps>();
        _props = defaultProps;
        _scanningEnabled = true;
        _barcodeItemOverlayViewLoadingText = nil;
        _barcodeItemOverlayViewBinders = nil;
        self.attached = false;

        self.scannerViewController = [RNScanbotBarcodeScannerViewControllerWrapper initController];
        self.scannerViewController.delegate = self;
        self.scannerViewController.trackingOverlayController.delegate = self;
    }

    return self;
}

- (void)didMoveToWindow {
    [super didMoveToWindow];

    if(self.window && !self.attached){
        [[self reactViewController] sbsdk_attachViewController:self.scannerViewController inView:self];
        self.attached = true;
    }
}

- (void)prepareForRecycle {
    self.scannerViewController.delegate = nil;
    self.scannerViewController.trackingOverlayController.delegate = nil;
    [self.scannerViewController sbsdk_detachViewController:self.scannerViewController];

    self.scannerViewController = nil;

    self.barcodeItemOverlayViewLoadingText = nil;
    self.barcodeItemOverlayViewBinders = nil;

    static const auto defaultProps = std::make_shared<const ScanbotBarcodeScannerViewProps>();
    self.attached = false;
    _props = defaultProps;
    [super prepareForRecycle];
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
    if (self.scannerViewController == nil) {
        self.scannerViewController = [RNScanbotBarcodeScannerViewControllerWrapper initController];
        self.scannerViewController.delegate = self;
        self.scannerViewController.trackingOverlayController.delegate = self;
    }

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

    SBSDKBarcodeScannerConfiguration *configuration = self.scannerViewController.copyCurrentConfiguration;
    SBSDKBaseScannerViewFinderConfiguration *finderConfig = self.scannerViewController.viewFinderConfiguration;
    SBSDKBaseScannerZoomConfiguration *zoomConfig = self.scannerViewController.zoomConfiguration;

    if(oldViewProps.flashEnabled != newViewProps.flashEnabled){
        [RNScanbotBarcodeScannerViewControllerWrapper setFlashEnabled:self.scannerViewController value:newViewProps.flashEnabled];
    }
    if(oldViewProps.scanningEnabled != newViewProps.scanningEnabled){
        self.scanningEnabled = newViewProps.scanningEnabled;
    }
    if(oldViewProps.hardwareButtonsEnabled != newViewProps.hardwareButtonsEnabled){
        [RNScanbotBarcodeScannerViewControllerWrapper setHardwareButtonsEnabled:self.scannerViewController value:newViewProps.hardwareButtonsEnabled];
    }
    // MARK: FinderConfig Props
    if(oldViewProps.finderEnabled != newViewProps.finderEnabled){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderEnabled:finderConfig value:newViewProps.finderEnabled];
    }
    if(oldViewProps.finderStrokeWidth != newViewProps.finderStrokeWidth){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderStrokeWidth:finderConfig value:newViewProps.finderStrokeWidth];
    }
    if(oldViewProps.finderStrokeColor != newViewProps.finderStrokeColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderStrokeColor:finderConfig value:RCTUIColorFromSharedColor(newViewProps.finderStrokeColor)];
    }
    if(oldViewProps.finderOverlayColor != newViewProps.finderOverlayColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderOverlayColor:finderConfig value:RCTUIColorFromSharedColor(newViewProps.finderOverlayColor)];
    }
    if(oldViewProps.finderInset != newViewProps.finderInset){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderInset:finderConfig
                                                                 top:newViewProps.finderInset.top
                                                                left:newViewProps.finderInset.left
                                                              bottom:newViewProps.finderInset.bottom
                                                               right:newViewProps.finderInset.right];
    }
    if(oldViewProps.finderRequiredAspectRatios != newViewProps.finderRequiredAspectRatios){
        [RNScanbotBarcodeScannerViewControllerWrapper setFinderRequiredAspectRatios:finderConfig
                                                                              width:newViewProps.finderRequiredAspectRatios.width
                                                                             height:newViewProps.finderRequiredAspectRatios.height];
    }
    // MARK: -
    // MARK: CameraConfig Props
    if(oldViewProps.cameraZoomFactor != newViewProps.cameraZoomFactor){
        [RNScanbotBarcodeScannerViewControllerWrapper setCameraZoomFactor:zoomConfig value:newViewProps.cameraZoomFactor];
    }
    if(oldViewProps.cameraZoomRange != newViewProps.cameraZoomRange){
        [RNScanbotBarcodeScannerViewControllerWrapper setCameraZoomRange:zoomConfig
                                                                 minZoom:newViewProps.cameraZoomRange.minZoom
                                                                 maxZoom:newViewProps.cameraZoomRange.maxZoom];
    }
    if(![self compareStringProps:oldViewProps.cameraModule withString:newViewProps.cameraModule]){
        [RNScanbotBarcodeScannerViewControllerWrapper setCameraDevice:self.scannerViewController value:[self toNSString:newViewProps.cameraModule]];
    }
    if(oldViewProps.minFocusDistanceLock != newViewProps.minFocusDistanceLock){
        [RNScanbotBarcodeScannerViewControllerWrapper setMinFocusDistanceLock:self.scannerViewController value:newViewProps.minFocusDistanceLock];
    }
    // MARK: -
    // MARK: Tracking Overlay Config
    if(oldViewProps.overlayEnabled != newViewProps.overlayEnabled){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayEnabled:self.scannerViewController value:newViewProps.overlayEnabled];
    }
    if(oldViewProps.overlayPolygonColor != newViewProps.overlayPolygonColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayPolygonColor:self.scannerViewController value:RCTUIColorFromSharedColor(newViewProps.overlayPolygonColor)];
    }
    if(oldViewProps.overlayStrokeColor != newViewProps.overlayStrokeColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayStrokeColor:self.scannerViewController value:RCTUIColorFromSharedColor(newViewProps.overlayStrokeColor)];
    }
    if(oldViewProps.overlayTextColor != newViewProps.overlayTextColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayTextColor:self.scannerViewController value:RCTUIColorFromSharedColor(newViewProps.overlayTextColor)];
    }
    if(oldViewProps.overlayTextContainerColor != newViewProps.overlayTextContainerColor){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayTextContainerColor:self.scannerViewController value:RCTUIColorFromSharedColor(newViewProps.overlayTextContainerColor)];
    }
    if(![self compareStringProps:oldViewProps.overlayTextFormat withString:newViewProps.overlayTextFormat]){
        [RNScanbotBarcodeScannerViewControllerWrapper setOverlayTextFormat:self.scannerViewController value:[self toNSString:newViewProps.overlayTextFormat]];
    }

    self.barcodeItemOverlayViewLoadingText = [self toNSString:newViewProps.overlayLoadingTextValue];

    if(newViewProps.overlayBarcodeItemOverlayViewBinder != oldViewProps.overlayBarcodeItemOverlayViewBinder){
        if (newViewProps.overlayBarcodeItemOverlayViewBinder) {
            if (self.barcodeItemOverlayViewBinders == nil) {
                self.barcodeItemOverlayViewBinders = [[NSMutableDictionary alloc] init];
            }
        } else {
            self.barcodeItemOverlayViewBinders = nil;
        }
    }

    // MARK: BarcodeScanningConfiguration
    if(oldViewProps.configFormatConfigurations != newViewProps.configFormatConfigurations){
        NSMutableArray<SBSDKBarcodeFormatConfigurationBase *> *formatConfigurations = [[NSMutableArray alloc] initWithCapacity:newViewProps.configExtractedDocumentFormats.size()];

        for(const ScanbotBarcodeScannerViewConfigFormatConfigurationsStruct &item : newViewProps.configFormatConfigurations){
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@{
                @"_type": [self toNSString: item._type],
                @"regexFilter": [self toNSString:item.regexFilter],
                @"minimumSizeScore": [NSNumber numberWithDouble:item.minimumSizeScore],
                @"addAdditionalQuietZone": @(item.addAdditionalQuietZone),
                @"minimum1DQuietZoneSize": [NSNumber numberWithDouble:item.minimum1DQuietZoneSize],
                @"minimumTextLength": [NSNumber numberWithDouble:item.minimumTextLength],
                @"maximumTextLength": [NSNumber numberWithDouble:item.maximumTextLength],
                @"returnStartEnd": @(item.returnStartEnd),
                @"stripCheckDigits": @(item.stripCheckDigits),
                @"checksum": @(item.checksum),
                @"code32": @(item.code32),
                @"code39": @(item.code39),
                @"pzn7": @(item.pzn7),
                @"pzn8": @(item.pzn8),
                @"tryCode39ExtendedMode": @(item.tryCode39ExtendedMode),
                @"useCode39CheckDigit": @(item.useCode39CheckDigit),
                @"gs1Handling": [self toNSString:item.gs1Handling],
                @"iata2of5": @(item.iata2of5),
                @"code25": @(item.code25),
                @"industrial2of5": @(item.industrial2of5),
                @"useIATA2OF5Checksum": @(item.useIATA2OF5Checksum),
                @"checksumAlgorithms": [self vectorStringToNSArray:item.checksumAlgorithms],
                @"ean8": @(item.ean8),
                @"ean13": @(item.ean13),
                @"upca": @(item.upca),
                @"upce": @(item.upce),
                @"extensions": [self toNSString: item.extensions],
                @"minimumValue": [NSNumber numberWithDouble:item.minimumValue],
                @"allowNarrowBarsOnly": @(item.allowNarrowBarsOnly),
                @"allowWideBarsOnly": @(item.allowWideBarsOnly),
                @"strictMode": @(item.strictMode),
                @"qr": @(item.qr),
                @"microQr": @(item.microQr),
                @"rmqr": @(item.rmqr),
                @"australiaPostCustomerFormat": [self toNSString:item.australiaPostCustomerFormat],
                @"formats": [self vectorStringToNSArray:item.formats],
                @"minimumNumberOfRequiredFramesWithEqualRecognitionResult": [NSNumber numberWithInt:item.minimumNumberOfRequiredFramesWithEqualRecognitionResult],
                @"minimumNumberOfRequiredFramesWithEqualRecognitionResultExtensionless": [NSNumber numberWithInt:item.minimumNumberOfRequiredFramesWithEqualRecognitionResultExtensionless]
            }
                                                               options:NSJSONWritingSortedKeys
                                                                 error:nil];
            if(jsonData != nil){
                NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                [formatConfigurations addObject:[SBSDKBarcodeFormatConfigurationBase fromJsonWithJson:jsonString]];
            }
        }

        configuration.barcodeFormatConfigurations = formatConfigurations;
    }
    if(oldViewProps.configExtractedDocumentFormats != newViewProps.configExtractedDocumentFormats){
        NSMutableArray<NSString *> *formats = [[NSMutableArray alloc] initWithCapacity:newViewProps.configExtractedDocumentFormats.size()];
        for (const std::string &str : newViewProps.configExtractedDocumentFormats) {
            [formats addObject:[self toNSString:str]];
        }

        [RNScanbotBarcodeScannerViewControllerWrapper setConfigExtractedDocumentFormats:configuration
                                                                                formats:formats];
    }
    if(oldViewProps.configOnlyAcceptDocuments != newViewProps.configOnlyAcceptDocuments){
        [RNScanbotBarcodeScannerViewControllerWrapper setConfigOnlyAcceptDocuments:configuration
                                                                             value:newViewProps.configOnlyAcceptDocuments];
    }
    if(oldViewProps.configEngineMode != newViewProps.configEngineMode){
        [RNScanbotBarcodeScannerViewControllerWrapper setConfigEngineMode:configuration
                                                                    value:[self toNSString:newViewProps.configEngineMode]];
    }
    if(oldViewProps.configReturnBarcodeImage != newViewProps.configReturnBarcodeImage){
        [RNScanbotBarcodeScannerViewControllerWrapper setConfigReturnBarcodeImage:configuration
                                                                            value:newViewProps.configReturnBarcodeImage];
    }
    if(oldViewProps.configOptimizedForOverlays != newViewProps.configOptimizedForOverlays){
        [RNScanbotBarcodeScannerViewControllerWrapper setConfigOptimizedForOverlays:configuration
                                                                              value:newViewProps.configOptimizedForOverlays];
    }
    if(oldViewProps.configAccumulation != newViewProps.configAccumulation){
        [RNScanbotBarcodeScannerViewControllerWrapper setConfigAccumulation:configuration
                                                           accumulationTime:newViewProps.configAccumulation.accumulationTime
                                                   removeUnconnectedResults:newViewProps.configAccumulation.removeUnconnectedResults
                                                                     method:[self toNSString:newViewProps.configAccumulation.method]];
    }

    [self.scannerViewController setConfiguration:configuration];
    self.scannerViewController.viewFinderConfiguration = finderConfig;
    self.scannerViewController.zoomConfiguration = zoomConfig;

    [super updateProps:props oldProps:oldProps];
}

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

- (void)bindBarcodeItemOverlayView:(nonnull NSString *)barcodeItemUuid bindingConfig:(nonnull NSString *)bindingConfigJson {
    [RNScanbotBarcodeScannerViewControllerWrapper updateBarcodeItemOverlayViewBinderInDictionary:self.barcodeItemOverlayViewBinders
                                                                                 barcodeItemUuid:barcodeItemUuid
                                                                barcodeItemOverlayViewConfigJson:bindingConfigJson];
}

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

- (void)barcodeScannerController:(SBSDKBarcodeScannerViewController *)controller
                 didScanBarcodes:(NSArray<SBSDKBarcodeItem *> * _Nonnull)codes {
    if (_eventEmitter == nullptr) return;
    if(codes.count == 0) return;


    NSString *result = [RNScanbotBarcodeScannerViewControllerWrapper jsonFromResultOrNil:codes];
    if (result != nil){
        const auto &eventEmitter = std::dynamic_pointer_cast<const facebook::react::ScanbotBarcodeScannerViewEventEmitter>(_eventEmitter);
        eventEmitter->onBarcodeScannerResult(facebook::react::ScanbotBarcodeScannerViewEventEmitter::OnBarcodeScannerResult{.result = std::string([result UTF8String])});

        [RNScanbotBarcodeScannerViewControllerWrapper addBarcodeItemOverlayViewInitialBinderInDictionary:self.barcodeItemOverlayViewBinders
                                                                                             loadingText:self.barcodeItemOverlayViewLoadingText
                                                                                                barcodes:codes];
    }
}

- (void)barcodeTrackingOverlay:(SBSDKBarcodeTrackingOverlayController *)controller didTapOnBarcode:(SBSDKBarcodeItem * _Nonnull)barcode; {

    if (_eventEmitter == nullptr) return;

    NSString *result = [RNScanbotBarcodeScannerViewControllerWrapper jsonFromBarcodeOrNil:barcode];
    if(result != nil){
        const auto &eventEmitter = std::dynamic_pointer_cast<const facebook::react::ScanbotBarcodeScannerViewEventEmitter>(_eventEmitter);
        eventEmitter->onSelectBarcodeResult(facebook::react::ScanbotBarcodeScannerViewEventEmitter::OnSelectBarcodeResult{.result = std::string([result UTF8String])});
    }

}

- (SBSDKBarcodeTrackedViewPolygonStyle *)barcodeTrackingOverlay:(SBSDKBarcodeTrackingOverlayController *)controller
                                                polygonStyleFor:(SBSDKBarcodeItem *)barcode
                                                  proposedStyle:(SBSDKBarcodeTrackedViewPolygonStyle *)proposedStyle {
    if (self.barcodeItemOverlayViewBinders != nil) {
        NSDictionary *barcodeItemOverlayViewBinding = [self.barcodeItemOverlayViewBinders objectForKey:[barcode uuid]];

        return [RNScanbotBarcodeScannerViewControllerWrapper scannedBarcodePolygonStyle:barcode
                                                          barcodeItemOverlayViewBinding:barcodeItemOverlayViewBinding
                                                                          proposedStyle:proposedStyle];
    } else {
        return proposedStyle;
    }
}

- (SBSDKBarcodeTrackedViewTextStyle *)barcodeTrackingOverlay:(SBSDKBarcodeTrackingOverlayController *)controller
                                                textStyleFor:(SBSDKBarcodeItem *)barcode
                                               proposedStyle:(SBSDKBarcodeTrackedViewTextStyle *)proposedStyle{
    if (self.barcodeItemOverlayViewBinders != nil) {
        NSDictionary *barcodeItemOverlayViewBinding = [self.barcodeItemOverlayViewBinders objectForKey:[barcode uuid]];

        return [RNScanbotBarcodeScannerViewControllerWrapper scannedBarcodeOverlayViewTextStyle:barcode
                                                                  barcodeItemOverlayViewBinding:barcodeItemOverlayViewBinding
                                                                                  proposedStyle:proposedStyle];
    } else {
        return proposedStyle;
    }
}

- (NSString * _Nonnull)barcodeTrackingOverlay:(SBSDKBarcodeTrackingOverlayController * _Nonnull)controller overrideTextFor:(SBSDKBarcodeItem * _Nonnull)barcode proposedString:(NSString * _Nonnull)proposedString {

    NSString * _Nonnull barcodeItemUuid = [barcode uuid];
    NSDictionary * _Nullable barcodeItemOverlayViewBinding = nil;

    if (self.barcodeItemOverlayViewBinders != nil) {
        barcodeItemOverlayViewBinding = [self.barcodeItemOverlayViewBinders objectForKey:barcodeItemUuid];
    }

    return [RNScanbotBarcodeScannerViewControllerWrapper scannedBarcodeOverlayViewText:barcodeItemUuid
                                                                        proposedString:proposedString
                                                         barcodeItemOverlayViewBinding:barcodeItemOverlayViewBinding];
}

- (BOOL)barcodeScannerControllerShouldDetectBarcodes:(SBSDKBarcodeScannerViewController *)controller {
    return self.scanningEnabled;
}

bool operator!=(ScanbotBarcodeScannerViewFinderInsetStruct const &i,ScanbotBarcodeScannerViewFinderInsetStruct const &j) {
    return !(i.left == j.left && i.top == j.top && i.bottom == j.bottom && i.right == j.right);
}

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

bool operator!=(ScanbotBarcodeScannerViewCameraZoomRangeStruct const &i, ScanbotBarcodeScannerViewCameraZoomRangeStruct const &j) {
    return !(i.maxZoom == j.maxZoom && i.minZoom == j.minZoom);
}

bool operator!=(std::vector<std::string> const &v1, std::vector<std::string> 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;
}

bool operator!=(std::vector<ScanbotBarcodeScannerViewConfigFormatConfigurationsStruct> const &v1, std::vector<ScanbotBarcodeScannerViewConfigFormatConfigurationsStruct> const &v2){

    if(v1.size() != v2.size()) return true;

    for(int i = 0; i< v1.size(); i++){
        if(
           v1[i]._type != v2[i]._type ||
           v1[i].regexFilter != v2[i].regexFilter ||
           v1[i].minimumSizeScore != v2[i].minimumSizeScore ||
           v1[i].addAdditionalQuietZone != v2[i].addAdditionalQuietZone ||
           v1[i].minimum1DQuietZoneSize != v2[i].minimum1DQuietZoneSize ||
           v1[i].minimumTextLength != v2[i].minimumTextLength ||
           v1[i].maximumTextLength != v2[i].maximumTextLength ||
           v1[i].returnStartEnd != v2[i].returnStartEnd ||
           v1[i].stripCheckDigits != v2[i].stripCheckDigits ||
           v1[i].checksum != v2[i].checksum ||
           v1[i].code32 != v2[i].code32 ||
           v1[i].code39 != v2[i].code39 ||
           v1[i].pzn7 != v2[i].pzn7 ||
           v1[i].pzn8 != v2[i].pzn8 ||
           v1[i].tryCode39ExtendedMode != v2[i].tryCode39ExtendedMode ||
           v1[i].useCode39CheckDigit != v2[i].useCode39CheckDigit ||
           v1[i].gs1Handling != v2[i].gs1Handling ||
           v1[i].iata2of5 != v2[i].iata2of5 ||
           v1[i].code25 != v2[i].code25 ||
           v1[i].industrial2of5 != v2[i].industrial2of5 ||
           v1[i].useIATA2OF5Checksum != v2[i].useIATA2OF5Checksum ||
           v1[i].checksumAlgorithms != v2[i].checksumAlgorithms ||
           v1[i].ean8 != v2[i].ean8 ||
           v1[i].ean13 != v2[i].ean13 ||
           v1[i].upca != v2[i].upca ||
           v1[i].upce != v2[i].upce ||
           v1[i].extensions != v2[i].extensions ||
           v1[i].minimumValue != v2[i].minimumValue ||
           v1[i].allowNarrowBarsOnly != v2[i].allowNarrowBarsOnly ||
           v1[i].allowWideBarsOnly != v2[i].allowWideBarsOnly ||
           v1[i].strictMode != v2[i].strictMode ||
           v1[i].qr != v2[i].qr ||
           v1[i].microQr != v2[i].microQr ||
           v1[i].rmqr != v2[i].rmqr ||
           v1[i].minimumValue != v2[i].minimumValue ||
           v1[i].allowNarrowBarsOnly != v2[i].allowNarrowBarsOnly ||
           v1[i].allowWideBarsOnly != v2[i].allowWideBarsOnly ||
           v1[i].strictMode != v2[i].strictMode ||
           v1[i].qr != v2[i].qr ||
           v1[i].australiaPostCustomerFormat != v2[i].australiaPostCustomerFormat ||
           v1[i].formats != v2[i].formats
           ){
               return true;
           }
    }

    return false;

}

bool operator!=(ScanbotBarcodeScannerViewConfigAccumulationStruct const &i, ScanbotBarcodeScannerViewConfigAccumulationStruct const &j) {
    return i.accumulationTime != j.accumulationTime ||
    i.method != j.method ||
    i.removeUnconnectedResults != j.removeUnconnectedResults;
}

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

- (NSArray*)vectorStringToNSArray:(std::vector<std::string>) vector {
    NSMutableArray* nsArray = [NSMutableArray array];

    for (auto const& value : vector) {
        [nsArray addObject:[self toNSString:value]];
    }

    return nsArray;
}

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

@end

Class<RCTComponentViewProtocol> ScanbotBarcodeScannerViewCls(void)
{
    return RNScanbotBarcodeScannerView.class;
}
#endif
