#import "ScanbotBarcodeSdk.h"

#import "ScanbotBarcodeSDKWrapper/ScanbotBarcodeSDKWrapper-Swift.h"
#import "ScanbotBarcodeSdkPluginResultDelegate.h"

#import <React/RCTUtils.h>

@implementation ScanbotBarcodeSdk
RCT_EXPORT_MODULE()

NSString *const BarcodeItemMapperEvent = @"barcodeItemMapperEvent";


RCT_EXPORT_METHOD(initializeSdk:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBWrapper initializeSDKWithConfiguration:configuration resultDelegate: [self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(getLicenseInfo:
                  (RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBWrapper getLicenseInfoWithResultDelegate: [self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(cleanup:
                  (RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBWrapper cleanupWithResultDelegate: [self createResultDelegate:resolve reject:reject]];
}


RCT_EXPORT_METHOD(startBarcodeScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    
    runOnMainThread(^{
        UIViewController *presentedViewController = [self parentViewController:reject];
        if (presentedViewController == NULL) {
            return;
        }
        
        [SBBRTUUI startBarcodeScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:[self createResultDelegate:resolve reject:reject]];
    });
}

RCT_EXPORT_METHOD(closeBarcodeScanner:
                  (RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    runOnMainThread(^{
        [SBBRTUUI closeBarcodeScannerWithResultDelegate: [self createResultDelegate:resolve reject:reject]];
    });
}

RCT_EXPORT_METHOD(startBatchBarcodeScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    
    runOnMainThread(^{
        UIViewController *presentedViewController = [self parentViewController:reject];
        if (presentedViewController == NULL) {
            return;
        }
        
        [SBBRTUUI startBatchBarcodeScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:[self createResultDelegate:resolve reject:reject]];
    });
}

RCT_EXPORT_METHOD(closeBatchBarcodeScanner:
                  (RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    runOnMainThread(^{
        [SBBRTUUI closeBatchBarcodeScannerWithResultDelegate: [self createResultDelegate:resolve reject:reject]];
    });
}

RCT_EXPORT_METHOD(startBarcodeScannerV2:(NSString*)configuration:(BOOL)barcodeItemMapperImplemented
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    
    runOnMainThread(^{
        UIViewController *presentedViewController = [self parentViewController:reject];
        if (presentedViewController == NULL) {
            return;
        }
        
        ScanbotBarcodeSdkPluginResultDelegate* delegate = [self createResultDelegate:resolve reject:reject];
        
        if (barcodeItemMapperImplemented) {
            [SBBRTUUI startBarcodeScannerV2WithParentViewController:presentedViewController
                                                      configurationString:configuration
                                                     resultDelegate:delegate
                                             mapBarcodeItemCallback: ^(NSDictionary<NSString *,id> * _Nonnull barcodeItem) {
                [self sendEventWithName:BarcodeItemMapperEvent body:barcodeItem];
            }];
        } else {
            [SBBRTUUI startBarcodeScannerV2WithParentViewController:presentedViewController
                                                      configurationString:configuration
                                                     resultDelegate:delegate
                                             mapBarcodeItemCallback:nil];
        }
        
    });
}

RCT_EXPORT_METHOD(closeBarcodeScannerV2:
                  (RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBRTUUI closeBarcodeScannerV2WithResultDelegate: [self createResultDelegate:resolve reject:reject]];
}


RCT_EXPORT_METHOD(onBarcodeItemMapper:(NSString*)barcodeItem:(NSDictionary * _Nullable)barcodeMappedData) {
    [SBBRTUUI onBarcodeItemMapperWithBarcodeItemUUID:barcodeItem barcodeMappedDataAsDictionary:barcodeMappedData];
}

RCT_EXPORT_METHOD(detectBarcodesOnImage:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    
    [SBBOperations detectBarcodesOnImageWithOptionsConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(extractImagesFromPDF:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    
    [SBBOperations extractImagesFromPDFWithOptionsConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(getImageData:(NSString *)imageFileUri
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBOperations getImageDataWithImageFilePath:imageFileUri resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

- (ScanbotBarcodeSdkPluginResultDelegate*) createResultDelegate: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
    return [[ScanbotBarcodeSdkPluginResultDelegate alloc] initWithResolveBlock:resolve andRejectBlock:reject];
}

- (UIViewController* _Nullable) parentViewController:(RCTPromiseRejectBlock)reject {
    UIViewController *presentedViewController = RCTPresentedViewController();
    if (presentedViewController == NULL) {
        reject(@"RTUUI_ERROR", @"No active view controller", nil);
        return NULL;
    }
    
    return presentedViewController;
}

+ (BOOL)requiresMainQueueSetup
{
    return NO;
}

- (NSArray<NSString *> *)supportedEvents {
    return @[BarcodeItemMapperEvent];
}

void runOnMainThread(void (^block)(void))
{
    if ([NSThread isMainThread]) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), block);
    }
}

@end
