#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(initialize:(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) {
    [SBSDKManager getLicenseInfoWithResultDelegate: [self createResultDelegate:resolve reject:reject]];
}

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

RCT_EXPORT_METHOD(startBarcodeScanner:(NSString*)configuration:(BOOL)barcodeItemMapperImplemented
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

        UIViewController *presentedViewController = [self parentViewController:reject];
        if (presentedViewController == NULL) {
            return;
        }

        ScanbotBarcodeSdkPluginResultDelegate* 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(scanBarcodesFromImage:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBBarcode scanFromImageWithOptions:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(scanBarcodesFromPdf:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBBarcode scanFromPDFWithOptions:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(parseBarcodeDocument:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBBarcode parseDocumentWithOptions:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(readImageData:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBImageProcessor readImageDataWithOptions:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(mockCamera:(NSDictionary *)params
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBSDKManager mockCameraWithOptions:params resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

//MARK: ImageRef
RCT_EXPORT_METHOD(imageRefSerialize:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefSerializeWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefDeserialize:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefDeserializeWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefFromImageFileUri:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefFromImageFileUriWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefFromEncodedBuffer:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefFromEncodedBufferWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefHibernate:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefHibernateWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefClear:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefClearWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefRelease:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefReleaseWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefInfo:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefInfoWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefSaveImage:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBImageRef imageRefSaveImageWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefEncodeImage:(NSDictionary *)args
                  withResolver:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {

    [SBImageRef imageRefEncodeImageWithOperationConfig:args resultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(makeSnapshot:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBImageRef imageRefProfilerSnapshotWithResultDelegate:[self createResultDelegate:resolve reject:reject]];
}

RCT_EXPORT_METHOD(imageRefReleaseAll:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject) {
    [SBImageRef imageRefReleaseAllWithResultDelegate:[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];
}

@end
