/********* MrzScanner.m Cordova Plugin Implementation *******/

#import <Cordova/CDV.h>
#import "MrzScanner/MrzScanner.h"

@interface MrzScanner()

@property MRZScannerController *mrzScannerController;

@end

@implementation MrzScanner

+ (BOOL)requiresMainQueueSetup {
    return YES;
}

MRZScannerType scannerTypeVar = TYPE_MRZ;
MRZEffortLevel effortLevelVar = EFFORT_LEVEL_TRY_HARDER;
int maxThreadsVar = 2;
NSString *myCallbackId;
NSString *hisCallbackId;
CDVPluginResult* pluginResult = nil;
CDVPluginResult* getSdkResult = nil;
bool flashToggleActivated = NO;
bool showCloseButtonVar = YES;
bool showFlashButtonVar = YES;
bool continuousScanning = NO;
bool ignoreDuplicates = YES;
bool extractPassportFull = NO;
bool extractPortrait = NO;
bool extractSignature = NO;
bool extractIdBack = NO;
float zoomFactorVar = 1.0;


- (void)startScanner:(CDVInvokedUrlCommand*)command {
    [self startScannerExec:command partialRect:CGRectMake(0, 0, 100, 100) base64String:nil];
}

- (void)startPartialViewScanner:(CDVInvokedUrlCommand*)command {
    int x = [command.arguments[0] ?: @(0) intValue];
    int y = [command.arguments[1] ?: @(0) intValue];
    int width = [command.arguments[2] ?: @(100) intValue];
    int height = [command.arguments[3] ?: @(100) intValue];
    
    [self startScannerExec:command partialRect:CGRectMake(x, y, width, height) base64String:nil];
}

-(void) startScannerExec:(CDVInvokedUrlCommand*)command base64String:(NSString*)base64String {
    [self startScannerExec:command partialRect:CGRectMake(0, 0, 100, 100) base64String:base64String];
}

-(void)startScannerExec:(CDVInvokedUrlCommand*)command partialRect:(CGRect)partialRect base64String:(NSString*)base64String {
    dispatch_async(dispatch_get_main_queue(), ^{
        myCallbackId = command.callbackId;
        UIViewController* currentVC = UIApplication.sharedApplication.keyWindow.rootViewController;
        self.mrzScannerController = [MRZScannerController new];
        if(flashToggleActivated){
            [self.mrzScannerController toggleFlash:YES];
        }
        self.mrzScannerController.delegate = self;
        [currentVC addChildViewController:self.mrzScannerController];
        [self.mrzScannerController setMaxCPUCores:maxThreadsVar];
        [self.mrzScannerController setScannerType:scannerTypeVar];
        [self.mrzScannerController setEffortLevel:effortLevelVar];
        [self.mrzScannerController setZoomFactor:zoomFactorVar];
        [self.mrzScannerController setContinuousScanningEnabled:continuousScanning];
        [self.mrzScannerController setIgnoreDuplicates:ignoreDuplicates];
        [self.mrzScannerController setShowCloseButton:showCloseButtonVar];
        [self.mrzScannerController setShowFlashButton:showFlashButtonVar];
        [MRZScannerController setExtractFullPassportImageEnabled:extractPassportFull];
        [MRZScannerController setExtractPortraitEnabled:extractPortrait];
        [MRZScannerController setExtractSignatureEnabled:extractSignature];
        [MRZScannerController setExtractIdBackEnabled:extractIdBack];
        
        if (base64String && ![base64String isEqualToString:@""]) {
            NSData *data = [[NSData alloc]initWithBase64EncodedString:base64String options:NSDataBase64DecodingIgnoreUnknownCharacters];
            [self.mrzScannerController setCustomOverlayImage:[UIImage imageWithData:data]];
        } else {
            [self.mrzScannerController setCustomOverlayImage:nil];
        }
        
        [self.mrzScannerController initUI:currentVC partialViewRect:partialRect];
    });
}

-(void)successfulScanWithResult:(MRZResultDataModel *)result {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSString* jsonString = result.toJSON;
        if (![jsonString containsString:@"given_names_readable"]) {
            jsonString = [jsonString stringByReplacingOccurrencesOfString:@"given_names" withString:@"given_names_readable"];
        }
        
        NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSError* err;
        NSMutableDictionary* successfulMrzScan = [[NSJSONSerialization JSONObjectWithData:data options:0 error:&err] mutableCopy];
        
        if (result.idBack) {
            NSData * data = UIImagePNGRepresentation(result.idBack);
            NSString *base64String = [data base64EncodedStringWithOptions:0];
            [successfulMrzScan setValue:base64String forKey:@"idBack"];
        } else if (result.fullImage) {
            NSData * data = UIImagePNGRepresentation(result.fullImage);
            NSString *base64String = [data base64EncodedStringWithOptions:0];
            [successfulMrzScan setValue:base64String forKey:@"passportImage"];
        } else if (result.portrait) {
            NSData * data = UIImagePNGRepresentation(result.portrait);
            NSString *base64String = [data base64EncodedStringWithOptions:0];
            [successfulMrzScan setValue:base64String forKey:@"portrait"];
        } else if (result.signature) {
            NSData * data = UIImagePNGRepresentation(result.signature);
            NSString *base64String = [data base64EncodedStringWithOptions:0];
            [successfulMrzScan setValue:base64String forKey:@"signature"];
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (!err) {
                pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:successfulMrzScan];
                if (continuousScanning) {
                    [pluginResult setKeepCallbackAsBool:YES];
                }
                [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
            }
            
            if (!continuousScanning) {
                [self->_mrzScannerController dismissViewControllerAnimated:YES completion:nil];
            }
        });
    });
}

-(void)successfulDocumentScanWithImageResult:(UIImage *)resultImage {
    NSData * data = UIImagePNGRepresentation(resultImage);
    NSString *successfulScanWithDocumentImage = [data base64EncodedStringWithOptions:0];
    
    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:successfulScanWithDocumentImage];
    [_mrzScannerController dismissViewControllerAnimated:YES completion:nil];
    [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
}

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

-(void)setScannerType:(CDVInvokedUrlCommand*)command{
    scannerTypeVar = [[command.arguments objectAtIndex:0]intValue];
}

-(void)setMaxThreads:(CDVInvokedUrlCommand*)command{
    maxThreadsVar = [[command.arguments objectAtIndex:0]intValue];
}

-(void)resumeScanner:(CDVInvokedUrlCommand*)command{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mrzScannerController resumeScanner];
    });
}

-(void)closeScanner:(CDVInvokedUrlCommand*)command{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mrzScannerController closeScanner];
    });
}

-(void)setExtractPortraitEnabled:(CDVInvokedUrlCommand*)command {
    extractPortrait = [[command.arguments objectAtIndex:0] boolValue];
    [MRZScannerController setExtractPortraitEnabled:extractPortrait];
}

-(void)setExtractFullPassportImageEnabled:(CDVInvokedUrlCommand*)command {
    extractPassportFull = [[command.arguments objectAtIndex:0] boolValue];
    [MRZScannerController setExtractFullPassportImageEnabled:extractPassportFull];
}

-(void)setExtractSignatureEnabled:(CDVInvokedUrlCommand*)command {
    extractSignature = [[command.arguments objectAtIndex:0] boolValue];
    [MRZScannerController setExtractSignatureEnabled:extractSignature];
}

-(void)setExtractIdBackEnabled:(CDVInvokedUrlCommand*)command {
    extractIdBack = [[command.arguments objectAtIndex:0] boolValue];
    [MRZScannerController setExtractPortraitEnabled:extractIdBack];
}

-(void)setNightModeActive:(CDVInvokedUrlCommand*)command{
    [self.mrzScannerController setNightModeActive:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)getSdkVersion:(CDVInvokedUrlCommand*)command{
    NSString *sdkVersionString = MRZScannerController.getSDKVersion;
    getSdkResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:sdkVersionString];
    [self.commandDelegate sendPluginResult:getSdkResult callbackId:command.callbackId];
}

-(void)registerWithLicenseKey:(CDVInvokedUrlCommand*)command{
    NSString *licenceKey = [command.arguments objectAtIndex:0];
    [MRZScannerController registerLicenseWithKey: licenceKey registerResultHandler:^(int result, NSError *error) {
      if (error) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.localizedDescription];
      } else {
          pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Success"];
      }
      [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
    }];
}

-(void)scanFromGallery:(CDVInvokedUrlCommand*)command{
    dispatch_async(dispatch_get_main_queue(), ^{
        [MRZScannerController scanFromGallery:UIApplication.sharedApplication.keyWindow.rootViewController delegate:self];
    });
    myCallbackId = command.callbackId;
}

-(void)setPassportActive:(CDVInvokedUrlCommand*)command{
    [MRZScannerController setPassportActive:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)setIDActive:(CDVInvokedUrlCommand*)command{
    [MRZScannerController setIDActive:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)setVisaActive:(CDVInvokedUrlCommand*)command{
    [MRZScannerController setVisaActive:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)setIgnoreInvalidCheckDigitsEnabled:(CDVInvokedUrlCommand*)command{
    [MRZScannerController setIngoreInvalidCheckDigits:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)scanImageFailed{
    NSString *scanFailed = @"Scan Failed!";

    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:scanFailed];
    [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
}

-(void)scannerWasDismissed{
    NSString *scannerWasDismissed = @"Scan Dismissed!";
    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:scannerWasDismissed];
    [pluginResult setKeepCallbackAsBool:NO];
    [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
}

-(void)permissionsWereDenied{
    NSString *permissionsWereDenied = @"Permissions Were Denied!";
    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:permissionsWereDenied];
    [pluginResult setKeepCallbackAsBool:NO];
    [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
}

-(void)setDateFormat:(CDVInvokedUrlCommand*)command{
    [MRZScannerController setDateFormat:[[command.arguments objectAtIndex:0]stringValue]];
}

-(void)setVibrateOnSuccessfulScan:(CDVInvokedUrlCommand*)command{
    [MRZScannerController enableVibrationOnSuccess:[[command.arguments objectAtIndex:0]boolValue]];
}

-(void)setContinuousScanningEnabled:(CDVInvokedUrlCommand*)command{
    continuousScanning = [[command.arguments objectAtIndex:0] boolValue];

    if(_mrzScannerController)
        [_mrzScannerController setContinuousScanningEnabled:continuousScanning];
}

- (void)setIgnoreDuplicatesEnabled:(CDVInvokedUrlCommand*)command {
    ignoreDuplicates = [[command.arguments objectAtIndex:0] boolValue];

    if(_mrzScannerController)
        [_mrzScannerController setIgnoreDuplicates:ignoreDuplicates];
}

- (void)setEffortLevel:(CDVInvokedUrlCommand *)command {
    effortLevelVar = [[command.arguments objectAtIndex:0] intValue];
}

- (void)startScannerWithCustomOverlay:(CDVInvokedUrlCommand *)command {
    NSString *base64String = [command.arguments objectAtIndex:0];
    [self startScannerExec:command base64String:base64String];
}

- (void)toggleFlash:(CDVInvokedUrlCommand *)command {
    bool toggleFlash = [[command.arguments objectAtIndex:0] boolValue];
    flashToggleActivated = toggleFlash;
    dispatch_async(dispatch_get_main_queue(), ^{
        if(self.mrzScannerController) {
            [self.mrzScannerController toggleFlash :toggleFlash];
        }
    });
}

- (void)setZoomFactor:(CDVInvokedUrlCommand *)command {
    float zoomFactor = [[command.arguments objectAtIndex:0] floatValue];
    zoomFactorVar = zoomFactor;
    dispatch_async(dispatch_get_main_queue(), ^{
        if(self.mrzScannerController) {
            [self.mrzScannerController setZoomFactor :zoomFactorVar];
        }
    });
}

- (void)setShowFlashButton:(CDVInvokedUrlCommand *)command {
    bool showFlashButton = [[command.arguments objectAtIndex:0] boolValue];
    showFlashButtonVar = showFlashButton;
    if (_mrzScannerController) {
        [self.mrzScannerController setShowFlashButton:showFlashButton];
    }
}

- (void)setShowCloseButton:(CDVInvokedUrlCommand *)command {
    bool showCloseButton = [[command.arguments objectAtIndex:0] boolValue];
    showCloseButtonVar = showCloseButton;
    if (_mrzScannerController) {
        [self.mrzScannerController setShowCloseButton:showCloseButton];
    }
}

@end
