#import "DefaultUILauncher.h"
#import "ObjectMapper.h"
#import "SBSDKPolygon+JSON.h"
#import "JSONMappings.h"
#import "RNScanbotSDK.h"
#import "BarcodeMapping.h"
#import "IdCardMapping.h"
#import "InternalScanbotStorageUtils.h"
#import "UIColor+JSON.h"
#import "LicensePlateMapping.h"
#import "JavaScriptEngine.h"
#import "RNProxyDelegate.h"

#define RTU_WRAPPER(block) [self presentRtuWithResolve:resolve andReject: reject vcBlock:^UIViewController *(NSObject<SBNWProxyDelegate> *delegate) { return block; }]

@import ScanbotSDK;
@import ScanbotSDKNativeWrapper;

@implementation DefaultUILauncher

static UIViewController* activeViewController = nil;

RCT_EXPORT_MODULE(SBSDKDefaultUi);

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

- (void) presentRtuWithResolve:(RCTPromiseResolveBlock)resolve
                     andReject:(RCTPromiseRejectBlock)reject
                       vcBlock:(UIViewController* (^)(NSObject<SBNWProxyDelegate>*))vcBlock
        
{
    RNProxyDelegate* delegate = [[RNProxyDelegate alloc] initWithResolveBlock:resolve andRejectBlock:reject];
    UIViewController* vc = vcBlock(delegate);
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentActiveViewController:vc];
}

RCT_EXPORT_METHOD(startDocumentScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createDocumentScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeDocumentScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUIDocumentScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startCroppingScreen:(NSDictionary*)page
                  configuration:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createCroppingScreenViewControllerWithPage:page configuration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeCroppingScreen:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUICroppingViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startMrzScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createMrzScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeMrzScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUIMRZScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startEHICScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createEhicScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeEHICScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUIHealthInsuranceCardScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startBarcodeScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createBarcodeScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeBarcodeScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUIBarcodeScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startLicensePlateScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createLicensePlateScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeLicensePlateScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUILicensePlateScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startBatchBarcodeScanner:(NSDictionary*)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createBatchBarcodeScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(closeBatchBarcodeScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUIBarcodesBatchScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startTextDataScanner:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createTextDataScannerViewControllerWithConfiguration:configuration delegate:delegate eventEmitterDelegate:nil]);
}

RCT_EXPORT_METHOD(closeTextDataScanner:(RCTPromiseResolveBlock)resolve
                  failure:(RCTPromiseRejectBlock)reject) {
    [self dismissActiveViewController: [SBSDKUITextDataScannerViewController class]];
    resolve(nil);
}

RCT_EXPORT_METHOD(startMedicalCertificateScanner:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createMedicalCertificateScannerViewControllerWithConfiguration:configuration delegate:delegate]);
}

RCT_EXPORT_METHOD(startGenericDocumentRecognizer:(NSDictionary *)configuration
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    RTU_WRAPPER([SBNWReadyToUseUi createGenericDocumentRecognizerViewControllerWithConfiguration:configuration delegate:delegate]);
}

- (void) presentActiveViewController:(UIViewController*) viewController {
    if (!viewController) {
        return;
    }
    
    UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
    [viewController setModalPresentationStyle:UIModalPresentationFullScreen];
    [rootViewController presentViewController:viewController animated:YES completion:nil];
    
    activeViewController = viewController;
}

- (_Bool) dismissActiveViewController:(Class _Nullable)vcClass {
    if (!activeViewController) {
        return false;
    }
    
    if (vcClass && ![activeViewController isKindOfClass:vcClass]) {
        return false;
    }
    
    [activeViewController dismissViewControllerAnimated:true completion:nil];
    activeViewController = nil;
    
    return true;
}

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