#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(startDocumentScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDocumentRTUUI startDocumentScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeDocumentScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDocumentRTUUI closeDocumentScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startFinderDocumentScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDocumentRTUUI startFinderDocumentScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeFinderDocumentScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDocumentRTUUI closeFinderDocumentScannerWithResultDelegate:delegate];
}

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

RCT_EXPORT_METHOD(closeCroppingScreen:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDocumentRTUUI closeCroppingScreenWithResultDelegate:delegate];
}

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

RCT_EXPORT_METHOD(closeMrzScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeMRZScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startEHICScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startEHICScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeEHICScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeEHICScannerWithResultDelegate:delegate];
}

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

RCT_EXPORT_METHOD(closeBarcodeScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBBRTUUI closeBarcodeScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startLicensePlateScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startLincesePlateScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeLicensePlateScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeLicensePlateScannerWithResultDelegate:delegate];
}

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

RCT_EXPORT_METHOD(closeBatchBarcodeScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBBRTUUI closeBatchBarcodeScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startTextDataScanner:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startTextDataScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeTextDataScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeTextDataScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startCheckRecognizer:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startCheckScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeCheckRecognizer:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject){
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeCheckScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startMedicalCertificateRecognizer:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startMedicalCertificateScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeMedicalCertificateRecognizer:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject
                  ){
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeMedicalCertificateScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startGenericDocumentRecognizer:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    UIViewController *presentedViewController = [self parentViewController:reject];
    if (presentedViewController == NULL) {
        return;
    }
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI startGDRScannerWithParentViewController:presentedViewController configuration:configuration resultDelegate:delegate];
}

RCT_EXPORT_METHOD(closeGenericDocumentRecognizer:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject
                  ){
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeGDRScannerWithResultDelegate:delegate];
}

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

RCT_EXPORT_METHOD(closeVinScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBDataRTUUI closeVINScannerWithResultDelegate:delegate];
}

RCT_EXPORT_METHOD(startBarcodeScannerV2:(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) {
        [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) {
    RNProxyDelegate *delegate = [self createResultDelegate:resolve reject:reject];
    [SBBRTUUI closeBarcodeScannerV2WithResultDelegate: delegate];
}

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

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

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


@end
