#import "RNScanbotBarcodeScannerViewControllerWrapper.h"


@implementation RNScanbotBarcodeScannerViewControllerWrapper

+ (SBSDKBarcodeScannerViewController * _Nonnull)initController {

    SBSDKBarcodeScannerViewController *scannerViewController = [[SBSDKBarcodeScannerViewController alloc] init];
    scannerViewController.generalConfiguration = [SBSDKBaseScannerGeneralConfiguration defaultConfiguration];
    scannerViewController.zoomConfiguration = [SBSDKBaseScannerZoomConfiguration defaultConfiguration];
    scannerViewController.energyConfiguration = [SBSDKBaseScannerEnergyConfiguration defaultConfiguration];

    SBSDKBaseScannerViewFinderConfiguration *finderConfig = [SBSDKBaseScannerViewFinderConfiguration defaultConfiguration];
    finderConfig.backgroundColor = [SBComponentUtils fromRgbAHex: @"#000000A9"];
    finderConfig.lineColor = [SBComponentUtils fromRgbAHex: @"#ffffffff"];
    scannerViewController.viewFinderConfiguration = finderConfig;

    //DEFAULTS
    scannerViewController.trackingOverlayController.configuration.polygonStyle.polygonBackgroundColor = [self uiColorToUiColorWithTransparentAlpha: [SBComponentUtils fromRgbAHex: @"#00CFA633"]];
    scannerViewController.trackingOverlayController.configuration.polygonStyle.polygonColor = [SBComponentUtils fromRgbAHex: @"#00CFA6CC"];
    scannerViewController.trackingOverlayController.configuration.textStyle.textColor = [SBComponentUtils fromRgbAHex: @"#000000"];
    scannerViewController.trackingOverlayController.configuration.textStyle.textBackgroundColor = [SBComponentUtils fromRgbAHex: @"#00CFA6CC"];

    return scannerViewController;
}

+ (void)setFlashEnabled:(SBSDKBarcodeScannerViewController * _Nonnull)controller value:(BOOL)value {
    controller.isFlashLightEnabled = value;
}

+ (void)setFinderEnabled:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config value:(BOOL)value {
    config.isViewFinderEnabled = value;
}

+ (void)setFinderStrokeWidth:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config value:(int)value {
    config.lineWidth = value;
}

+ (void)setFinderStrokeColor:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config value:(UIColor * _Nullable)value {
    config.lineColor = value != nil ? value : [SBComponentUtils fromRgbAHex: @"#ffffffff"];
}

+ (void)setFinderOverlayColor:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config value:(UIColor * _Nullable)value {
    config.backgroundColor = value != nil ? value : [SBComponentUtils fromRgbAHex: @"#000000A9"];
}

+ (void)setFinderInset:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config
                   top:(float)top
                  left:(float)left
                bottom:(float)bottom
                 right:(float)right {
    config.minimumInset = UIEdgeInsetsMake(top, left, bottom, right);
}

+ (void)setFinderRequiredAspectRatios:(SBSDKBaseScannerViewFinderConfiguration * _Nonnull)config
                                width:(double)width
                               height:(double)height {
    config.aspectRatio = [[SBSDKAspectRatio alloc] initWithWidth:width height:height];
}

+ (void)setCameraZoomFactor:(SBSDKBaseScannerZoomConfiguration * _Nonnull)config value:(float)value {
    config.initialZoomFactor = (value*100)/100;
}

+ (void)setCameraZoomRange:(SBSDKBaseScannerZoomConfiguration * _Nonnull)config minZoom:(float)minZoom maxZoom:(float)maxZoom{
    config.zoomRange =  [[SBSDKZoomRange alloc] initWithMinZoom:minZoom andMaxZoom:maxZoom];
}

+ (void)setCameraDevice:(SBSDKBarcodeScannerViewController * _Nonnull)controller value:(NSString * _Nullable)value {
    SBSDKCameraDevice *cameraConfig = value != NULL ? [SBComponentUtils cameraDeviceToNative:value] : NULL;

    if (cameraConfig != NULL) {
        controller.cameraDevice = cameraConfig;
    } else {
        controller.cameraDevice = [SBSDKCameraDevice defaultBackFacingCamera];
    }
}

+ (void)setMinFocusDistanceLock:(SBSDKBarcodeScannerViewController * _Nonnull)controller value:(BOOL)value {
    if(value){
        [controller beginFocusLockAtLensPosition:0.0f];
    } else {
        [controller endFocusLock];
    }
}

+ (void)setLowPowerMode:(SBSDKBarcodeScannerViewController * _Nonnull)controller value:(BOOL)value {
    if(value){
        if(!controller.isEnergySavingActive) [controller startEnergySaving];
    } else {
        if(controller.isEnergySavingActive) [controller endEnergySaving];
    }
}

+ (void)freezeCamera:(SBSDKBarcodeScannerViewController * _Nonnull)controller {
    [controller freezeCamera];
}

+ (void)unfreezeCamera:(SBSDKBarcodeScannerViewController * _Nonnull)controller {
    [controller unfreezeCamera];
}

+ (NSString *) jsonFromResultOrNil:(NSArray<SBSDKBarcodeItem *> * _Nonnull)codes {
    if(!codes || codes.count == 0) return nil;

    NSArray<NSDictionary *> * _Nullable result = [SBComponentUtils nativeResultsToDictionary:codes];
    if(result != NULL) {
        NSData *data = [NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingFragmentsAllowed error:nil];
        return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }

    return nil;
}

+ (NSString *) jsonFromBarcodeOrNil:(SBSDKBarcodeItem * _Nonnull)code {

    NSArray<NSDictionary *> * _Nullable result = [SBComponentUtils nativeResultsToDictionary:@[code]];
    if(result != NULL && result.firstObject != nil) {
        NSDictionary *firstObject = result.firstObject;
        NSData *data = [NSJSONSerialization dataWithJSONObject:firstObject options:NSJSONWritingFragmentsAllowed error:nil];
        return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }

    return nil;
}

+ (void)setOverlayEnabled:(SBSDKBarcodeScannerViewController *)config value:(BOOL)value {
    config.isTrackingOverlayEnabled = value;
}

+ (void)setOverlayPolygonColor:(SBSDKBarcodeScannerViewController *)config  value:(UIColor * _Nullable)value {
    config.trackingOverlayController.configuration.polygonStyle.polygonBackgroundColor = [self uiColorToUiColorWithTransparentAlpha:value != nil ? value : [SBComponentUtils fromRgbAHex: @"#00CFA633"]];
}

+ (void)setOverlayStrokeColor:(SBSDKBarcodeScannerViewController *)config value:(UIColor * _Nullable)value {
    config.trackingOverlayController.configuration.polygonStyle.polygonColor = value != nil ? value : [SBComponentUtils fromRgbAHex: @"#00CFA6CC"];
}

+ (void)setOverlayTextColor:(SBSDKBarcodeScannerViewController *)config value:(UIColor * _Nullable)value {
    config.trackingOverlayController.configuration.textStyle.textColor = value != nil ? value : [SBComponentUtils fromRgbAHex: @"#000000"];
}

+ (void)setOverlayTextContainerColor:(SBSDKBarcodeScannerViewController *)config value:(UIColor * _Nullable)value {
    config.trackingOverlayController.configuration.textStyle.textBackgroundColor = value != nil ? value : [SBComponentUtils fromRgbAHex: @"#00CFA6CC"];
}

+ (void)setOverlayTextFormat:(SBSDKBarcodeScannerViewController * _Nonnull)config value:(NSString * _Nullable)value {
    [config.trackingOverlayController.configuration.textStyle setTrackingOverlayTextFormat:[SBComponentUtils barcodeOverlayTextFormatToNative:value]];
}

+ (void)setHardwareButtonsEnabled:(SBSDKBarcodeScannerViewController *)controller value:(BOOL)value {
    controller.hardwareButtonsEnabled = value;
}

+ (void)setConfigExtractedDocumentFormats:(SBSDKBarcodeScannerConfiguration * _Nonnull)config formats:(NSArray<NSString *> * _Nullable)formats {
    config.extractedDocumentFormats = [SBComponentUtils barcodeDocumentFormatToNative:formats];
}

+ (void)setConfigOnlyAcceptDocuments:(SBSDKBarcodeScannerConfiguration * _Nonnull)config value:(BOOL)value {
    config.onlyAcceptDocuments = value;
}

+ (void)setConfigReturnBarcodeImage:(SBSDKBarcodeScannerConfiguration * _Nonnull)config value:(BOOL)value {
    config.returnBarcodeImage = value;
}

+ (void)setConfigEngineMode:(SBSDKBarcodeScannerConfiguration * _Nonnull)config value:(NSString * _Nullable)value {
    config.engineMode = [SBComponentUtils barcodeEngineModeToNative:value];
}

+ (void)setConfigAccumulation:(SBSDKBarcodeScannerConfiguration * _Nonnull)config
             accumulationTime:(int)accumulationTime
     removeUnconnectedResults:(BOOL)removeUnconnectedResults
                       method:(NSString * _Nullable)method {
    [config setAccumulationConfig: [[SBSDKBarcodeAccumulationConfiguration alloc]
                                    initWithAccumulationTime: accumulationTime
                                    removeUnconnectedResults: removeUnconnectedResults
                                    method: [method isEqual: @"INTERPOLATE_BY_CAMERA"] ?
                                    SBSDKBarcodeAccumulationMethodInterpolateByCamera : SBSDKBarcodeAccumulationMethodLastVisible
                                   ]];
}

+ (void)setConfigOptimizedForOverlays:(SBSDKBarcodeScannerConfiguration * _Nonnull)config
                                value:(BOOL)value {
    [config setOptimizedForOverlays:value];
}

+ (void)addBarcodeItemOverlayViewInitialBinderInDictionary:(NSMutableDictionary * _Nullable)dictionary
                                               loadingText:(NSString * _Nullable)loadingText
                                                  barcodes:(NSArray<SBSDKBarcodeItem *> * _Nonnull)barcodes {

    if (dictionary != nil) {
        for (SBSDKBarcodeItem* barcode in barcodes) {
            NSString* barcodeItemUuid = [barcode uuid];

            if ([dictionary objectForKey:barcodeItemUuid] == nil) {
                if(loadingText != nil) {
                    [dictionary setValue:@{@"text": loadingText} forKey:barcodeItemUuid];
                } else {
                    [dictionary setValue:@{} forKey:barcodeItemUuid];
                }
            }
        }
    }
}

+ (void)updateBarcodeItemOverlayViewBinderInDictionary:(NSMutableDictionary * _Nullable)dictionary
                                       barcodeItemUuid:(NSString * _Nonnull)barcodeItemUuid
                      barcodeItemOverlayViewConfigJson:(NSString * _Nonnull)barcodeItemOverlayViewConfigJson {

    if (dictionary != nil && [dictionary objectForKey:barcodeItemUuid] != nil) {
        NSError *fjsonError;
        NSData *objectData = [barcodeItemOverlayViewConfigJson dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *bindingPolygonStyleConfig = [NSJSONSerialization JSONObjectWithData:objectData
                                                                                  options:NSJSONReadingMutableContainers
                                                                                    error:&fjsonError];

        long lastBind = (long)([[NSDate date] timeIntervalSince1970] * 1000.0);
        [bindingPolygonStyleConfig setValue:[NSNumber numberWithLong:lastBind] forKey:@"lastBind"];

        [dictionary setObject:bindingPolygonStyleConfig forKey:barcodeItemUuid];
    }
}

+ (SBSDKBarcodeTrackedViewPolygonStyle * _Nonnull) scannedBarcodePolygonStyle:(SBSDKBarcodeItem * _Nonnull)barcode
                                                barcodeItemOverlayViewBinding:(NSDictionary * _Nonnull) barcodeItemOverlayViewBinding
                                                                proposedStyle:(SBSDKBarcodeTrackedViewPolygonStyle * _Nonnull)proposedStyle {
    SBSDKBarcodeTrackedViewPolygonStyle * _Nonnull newStyle = proposedStyle.copy;

    NSString* strokeColor = [barcodeItemOverlayViewBinding valueForKey:@"strokeColor"];
    if(strokeColor != nil) {
        newStyle.polygonColor = [SBComponentUtils fromRgbAHex:strokeColor];
    }

    NSString* polygonColor = [barcodeItemOverlayViewBinding valueForKey:@"polygonColor"];
    if(polygonColor != nil) {
        newStyle.polygonBackgroundColor = [self uiColorToUiColorWithTransparentAlpha:[SBComponentUtils fromRgbAHex:polygonColor]];
    }

    return newStyle;
}

+ (SBSDKBarcodeTrackedViewTextStyle * _Nonnull) scannedBarcodeOverlayViewTextStyle:(SBSDKBarcodeItem * _Nonnull)barcode
                                                     barcodeItemOverlayViewBinding:(NSDictionary * _Nonnull) barcodeItemOverlayViewBinding
                                                                     proposedStyle:(SBSDKBarcodeTrackedViewTextStyle * _Nonnull)proposedStyle {
    if ([self useGeneralSelectionOverlayConfig:barcodeItemOverlayViewBinding]) {
        return proposedStyle;
    }

    SBSDKBarcodeTrackedViewTextStyle * _Nonnull newStyle = proposedStyle.copy;

    NSString* textColor = [barcodeItemOverlayViewBinding valueForKey:@"textColor"];
    if(textColor != nil) {
        newStyle.textColor = [SBComponentUtils fromRgbAHex:textColor];
    }

    NSString* textContainerColor = [barcodeItemOverlayViewBinding valueForKey:@"textContainerColor"];
    if(textContainerColor != nil) {
        newStyle.textBackgroundColor = [SBComponentUtils fromRgbAHex:textContainerColor];
    }

    return newStyle;
}

+ (NSString * _Nonnull) scannedBarcodeOverlayViewText:(NSString * _Nonnull)barcodeItemUuid
                                       proposedString:(NSString * _Nonnull)proposedString
                        barcodeItemOverlayViewBinding:(NSDictionary * _Nullable) barcodeItemOverlayViewBinding {

    NSString * _Nonnull resultText = proposedString;

    if(barcodeItemOverlayViewBinding != nil) {

        NSString* bindedText = [barcodeItemOverlayViewBinding valueForKey:@"text"];
        if(bindedText != nil) {
            resultText = bindedText;
        } else {
            resultText = proposedString;
        }
    }

    return resultText;
}

+ (BOOL) useGeneralSelectionOverlayConfig: (NSDictionary * _Nonnull) barcodeItemOverlayViewBinding {
    NSNumber* _Nullable refreshRate = [barcodeItemOverlayViewBinding valueForKey:@"refreshRate"];
    NSNumber* _Nullable lastBind = [barcodeItemOverlayViewBinding valueForKey:@"lastBind"];

    long currentTimeInMs = (long)([[NSDate date] timeIntervalSince1970] * 1000.0);

    return (refreshRate != nil  && refreshRate.intValue > 0) &&
    (lastBind != nil && lastBind.longValue > 0) &&
    (currentTimeInMs - lastBind.longValue >= refreshRate.intValue);
}

+ (UIColor * _Nonnull) uiColorToUiColorWithTransparentAlpha: (UIColor * _Nonnull) originalColor {
    CGFloat red,green,blue,alpha;

    [originalColor getRed:&red green:&green blue:&blue alpha:&alpha];

    return [UIColor colorWithRed:red green:green blue:blue alpha:(alpha * 0.2)];
}

@end
