
#import "RNGeniusScan.h"

#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
#import <GSSDK/GSSDK.h>
#import <GSSDK/GSSDK-Swift.h>

@interface RNGeniusScan()
@property (nonatomic, strong) GSKScanFlow *scanner;
- (void)presentViewController:(UIViewController *)viewController rejecter:(RCTPromiseRejectBlock)reject;
@end

@implementation RNGeniusScan

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

- (void)presentViewController:(UIViewController *)viewController rejecter:(RCTPromiseRejectBlock)reject {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIViewController *root = RCTPresentedViewController();
        @try {
            [root presentViewController:viewController animated:YES completion:nil];
        }
        @catch (NSException *exception) {
            reject(exception.name, exception.reason, nil);
        }
    });
}

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(setLicenseKey:(NSString *)licenseKey autoRefresh:(BOOL)autoRefresh resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [GSK setLicenseKey:licenseKey autoRefresh:autoRefresh];
    resolve(nil);
}

RCT_EXPORT_METHOD(scanWithConfiguration:(NSDictionary *)scanOptions
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject
                  ) {
    NSError *error = nil;
    GSKScanFlowConfiguration *configuration = [GSKScanFlowConfiguration configurationWithDictionary:scanOptions error:&error];
    if (!configuration) {
        reject([NSString stringWithFormat:@"%@ error %d", error.domain, error.code], error.localizedDescription, error);
        return;
    }

    self.scanner = [GSKScanFlow scanFlowWithConfiguration:configuration];

    dispatch_async(dispatch_get_main_queue(), ^{
        UIViewController *root = RCTPresentedViewController();
        @try {
            [self.scanner startFromViewController:root onSuccess:^(GSKScanFlowResult * _Nonnull result) {
                resolve([result dictionary]);
            } failure:^(NSError *error) {
              reject([NSString stringWithFormat:@"%@ error %d", error.domain, error.code], error.localizedDescription, error);
            }];
        }
        @catch (NSException *exception) {
            reject(exception.name, exception.reason, nil);
        }
    });
}

RCT_EXPORT_METHOD(generateDocument:(NSDictionary *)documentDictionary
                  withConfiguration:(NSDictionary *)configurationDictionary
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject
                  ) {
    NSError *error = nil;
    GSKDocumentGeneratorConfiguration *configuration = [[GSKDocumentGeneratorConfiguration alloc] initWithDictionary:configurationDictionary error:&error];
    if (!configuration) {
        reject([NSString stringWithFormat:@"%@ error %d", error.domain, error.code], error.localizedDescription, error);
        return;
    }

    GSKPDFDocument *document = [[GSKPDFDocument alloc] initWithDictionary:documentDictionary error:&error];
    if (!document) {
        reject([NSString stringWithFormat:@"%@ error %d", error.domain, error.code], error.localizedDescription, error);
        return;
    }

    BOOL success = [[GSKDocumentGenerator alloc] generate:document configuration:configuration error:&error];
    if (success) {
        resolve(nil);
    } else {
        reject([NSString stringWithFormat:@"%@ error %d", error.domain, error.code], @"Document generation failed.", error);
    }
}

@end
