#import "RNScanbotSDKUI.h"

@implementation RNScanbotRTUUI

NSString *const BarcodeItemMapperEvent = @"barcodeItemMapperEvent";

RCT_EXPORT_MODULE(RNScanbotRTUUI);

//MARK: Utils
// Necessary so that the start* methods get called on the UI thread.
- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

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

- (RNProxyDelegate*) createResultDelegate: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
    return [[RNProxyDelegate 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;
}

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

//MARK: RTU-UI
RCT_EXPORT_METHOD(startBarcodeScanner:(NSString*)configuration:(BOOL)barcodeItemMapperImplemented
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];

    if (barcodeItemMapperImplemented) {
        [SBBarcode startScannerWithParentViewController:presentedViewController
                                                  stringConfiguration:configuration
                                                 resultDelegate:delegate
                                         mapBarcodeItemCallback: ^(NSDictionary<NSString *,id> * _Nonnull barcodeItem) {
            [self sendEventWithName:BarcodeItemMapperEvent body:barcodeItem];
        }];
    } else {
        [SBBarcode startScannerWithParentViewController:presentedViewController
                                             stringConfiguration:configuration
                                                 resultDelegate:delegate
                                         mapBarcodeItemCallback:nil];
    }
}

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

RCT_EXPORT_METHOD(startDocumentScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDDocument startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startCroppingScreen:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDDocument startCroppingScreenWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startMrzScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDMrz startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startTextPatternScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDTextRecognition startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startCreditCardScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDCreditCard startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startCheckScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDCheck startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startDDEScreen:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDDocumentDataExtractor startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(startVinScanner:(NSString *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate* delegate = [self createResultDelegate:resolve reject:reject];
    [SBDVin startScannerWithParentViewController:presentedViewController stringConfiguration:configuration resultDelegate:delegate];
}

@end
