//#import "MBOverlayViewControllerDelegate.h"
//#import "MBRecognizerSerializers.h"
//#import "MBOverlaySettingsSerializers.h"
//#import "MBRecognizerWrapper.h"
//#import "MBSerializationUtils.h"

#import <Foundation/Foundation.h>
#import "VFYSDK.h"
#import <React/RCTConvert.h>
#import <MicroBlink/MicroBlink.h>
//#import <BlinkCard/BlinkCard.h>


#import "VFYIDGuideWrapper.h"
#import "VFYIDSuccessWrapper.h"
#import "VFYIDFailGuideWrapper.h"
#import "VFYCardGuideWrapper.h"
#import "VFYConstant.h"
#import "VFYDeviceTypes.h"
#import "CombinedRecognizerResult+Property.h"
#import "VFYIDSelfieGuideWrapper.h"
#import "ResultModelIdFail.h"
#import "ResultModelCard.h"
#import "VFYLicense.h"


const NSString *RESULT_LIST = @"resultList";
NSString * const RESULT_CAPTURED_FULL_IMAGE = @"capturedFullImage";
const NSString *CANCELLED = @"cancelled";
const int COMPRESSED_IMAGE_QUALITY = 90;


typedef NS_ENUM(NSUInteger, PPImageType) {
    PPImageTypeFace,
    PPImageTypeDocument,
    PPImageTypeSuccessful,
};

@interface VFYSDK () //<MBOverlayViewControllerDelegate>

@property (nonatomic, strong) MBRecognizerCollection *recognizerCollection;
@property (nonatomic) id<MBRecognizerRunnerViewController> scanningViewController;

@property (nonatomic, strong) RCTPromiseResolveBlock promiseResolve;
@property (nonatomic, strong) RCTPromiseRejectBlock promiseReject;


@property (nonatomic) MBImage *highResImage;
@property (nonatomic, weak) VFYIDGuideWrapper *idGuiWrapper;
@property (nonatomic, weak) VFYCardGuideWrapper *cardGuiWrapper;
/* currentcontroller is used to remove child controller from parent CDVMicroblinkScanner **/
@property (nonatomic, weak) UIViewController *currentController;
@property (nonatomic, strong) NSString* languageBundlePath;
@property (nonatomic, retain) VFYVerifyApp *sharedInstance;
@property (nonatomic) componentCallDirectly callDirectlyFlag;
@property (nonatomic, strong) NSString* cardTwoLicense;
@property (nonatomic) CFTimeInterval auditEventDuration;
@property (nonatomic) CFTimeInterval auditScanDuration;
@property (assign) bool sendMoney;
@property (nonatomic, strong) NSBundle *bundlePath;

@end

// promise reject message codes
static NSString* const kErrorLicenseKeyDoesNotExists = @"ERROR_LICENSE_KEY_DOES_NOT_EXISTS";
static NSString* const kErrorCoordniatorDoesNotExists = @"COORDINATOR_DOES_NOT_EXISTS";
static NSString* const kStatusScanCanceled = @"STATUS_SCAN_CANCELED";

// NSError Domain
static NSString* const MBErrorDomain = @"microblink.error";

@implementation VFYSDK

RCT_EXPORT_MODULE(BlinkIDIos);


@synthesize idGuiWrapper, cardGuiWrapper, currentController;
@synthesize sharedInstance;
@synthesize auditEventDuration, auditScanDuration;

//RCT_EXPORT_MODULE(BlinkIDIos);

- (instancetype)init {
    if (self = [super init]) {
    }
    return self;
}

+ (BOOL)requiresMainQueueSetup {
    return YES;
}

/**
 Method  sanitizes the dictionary replaces all occurances of NSNull with nil

 @param dictionary JSON objects
 @return new dictionary with NSNull values replaced with nil
 */
- (NSDictionary *)sanitizeDictionary:(NSDictionary *)dictionary {
    NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] initWithDictionary:dictionary];
    for (NSString* key in dictionary.allKeys) {
        if (mutableDictionary[key] == [NSNull null]) {
            mutableDictionary[key] = nil;
        }
    }
    return mutableDictionary;
}


/**
  * Call identity scanning
 */
RCT_REMAP_METHOD(scanWithIdentity, scanWithIdentity:(NSDictionary *)jsonCustomeSettings license:(NSDictionary *)jsonLicense resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    
    self.promiseResolve = resolve;
    self.promiseReject = reject;
  
    [self setInitialSetting:jsonLicense customeSetting:jsonCustomeSettings];
    self.callDirectlyFlag = Directly;
    [self callIdSuccess];
    
}

/**
  * Call card scanning
 */
RCT_REMAP_METHOD(scanWithCard, scanWithCard:(NSDictionary *)jsonCustomeSettings license:(NSDictionary *)jsonLicense resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    
    self.promiseResolve = resolve;
    self.promiseReject = reject;
    
    [self setInitialSetting:jsonLicense customeSetting:jsonCustomeSettings];
    [self cardCase:nil];
}

/**
  * Call identity scanning with selfie
 */
  RCT_REMAP_METHOD(scanWithIdSelfieCombine, scanWithIdSelfieCombine:(NSDictionary *)jsonCustomeSettings license:(NSDictionary *)jsonLicense resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    
    self.promiseResolve = resolve;
    self.promiseReject = reject;

    [self setInitialSetting:jsonLicense customeSetting:jsonCustomeSettings];
    self.callDirectlyFlag = InDirectly;
    self.sendMoney = true;
    [self callIdSuccess];
}

/**
  * Call card scanning in sendmoney
 */
RCT_REMAP_METHOD(scanWithCardSendMoney, scanWithCardSendMoney:(NSDictionary *)jsonCustomeSettings license:(NSDictionary *)jsonLicense resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  
    self.promiseResolve = resolve;
    self.promiseReject = reject;

    [self setInitialSetting:jsonLicense customeSetting:jsonCustomeSettings];
    [self cardCase:true];
}

- (void) setInitialSetting:(NSDictionary *)jsonLicense customeSetting:(NSDictionary *)jsonCustomSetting {
  
    NSDictionary *jsonLicenses = [self sanitizeDictionary:jsonLicense];
    NSDictionary *jsonCustomSettings = [self sanitizeDictionary:jsonCustomSetting];
    
  
    [VFYLicense setLicense:jsonLicenses];
    sharedInstance = [VFYVerifyApp sharedInstance];
    
    [sharedInstance setLanguage:nil];
    [sharedInstance setDefaultValues];
    [self setCustomSetting:jsonCustomSettings SharedInstanced:sharedInstance];
    
    if([[sharedInstance language] length] == 0){
        NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
        NSString *OSLanguage = [Utilities setOSLanguage:language];
        [sharedInstance setLanguage:OSLanguage];
    }
    self.bundlePath = [NSBundle bundleForClass:[VFYVerifyApp class]];
}



#pragma MARK - Private Helper Method

- (void) selectedComponent:(NSString*) scanType {
    NSString *theString;
    if([scanType length]>0) {
        theString = [scanType lowercaseString];
    } else {
        [self closeParentView:(NSDictionary*)[NSNull null]];
        return;
    }
    //Added cardsendmoney to traces duration in send money process
    NSArray *items = @[@"idsuccess", @"idfailed", @"selfie", @"card", @"idselfiecombine", @"cardsendmoney"];
    int item = (int)[items indexOfObject:theString];
    switch (item) {
        case 0:
            self.callDirectlyFlag = Directly;
            [self callIdSuccess];
           break;
        case 1:
            [self failedCase:Directly];
           break;
        case 2:
            [self selfieCase:nil];
           break;
        case 3:
            [self cardCase:nil];
           break;
        case 4:
            self.callDirectlyFlag = InDirectly;
            self.sendMoney = true;
            [self callIdSuccess];
           break;
        case 5:
            [self cardCase:true];
            break;
        default:
            [self closeParentView:(NSDictionary*)[NSNull null]];
           break;
    }
}

- (void) callIdSuccess {
    //@[][1];
    dispatch_async(dispatch_get_main_queue(), ^{
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:VFY_MAIN_STORYBOARD bundle:self.bundlePath];
        UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:VFY_NAVIGATION_IDGUIDE_STORYBOARD];
        [self setNavigationBoder:nav];
        [self setNavigationAppearance];
        VFYIDGuideWrapper *vc = [storyboard instantiateViewControllerWithIdentifier:VFY_IDGUIDE_STORYBOARD];
        if(self.sendMoney){
            vc.sendMoney=self.sendMoney;
        }
        vc.idGuide = self;
        vc.sharedInstance = self.sharedInstance;
        vc.callDirectlyFlag = self.callDirectlyFlag;
        [nav pushViewController:vc animated:YES];
        
        UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        [rootViewController presentViewController:nav animated:YES completion:nil];
    });
}

- (void) cardCase:(bool) sendMoney {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:VFY_MAIN_STORYBOARD bundle:self.bundlePath];
        UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:VFY_NAVIGATION_CARDGUIDE_STORYBOARD];
        [self setNavigationBoder:nav];
        [self setNavigationAppearance];
        VFYCardGuideWrapper *vc = [storyboard instantiateViewControllerWithIdentifier:VFY_CARDGUIDE_STORYBOARD];
        if(sendMoney){
            vc.sendMoney=sendMoney;
        }
        vc.cardGuide = self;
        [nav pushViewController:vc animated:YES];
      
        UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        [rootViewController presentViewController:nav animated:YES completion:nil];
    });
}

- (void) selfieCase:(NSString*) faceImage {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:VFY_MAIN_STORYBOARD bundle:self.bundlePath];
        UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:VFY_NAVIGATION_IDGUIDE_STORYBOARD];
        [self setNavigationBoder:nav];
        [self setNavigationAppearance];
        VFYIDSelfieGuideWrapper *newView = [storyboard instantiateViewControllerWithIdentifier:VFY_SELFIE_STORYBOARD];
        newView.callDirectlyFlag = Directly;
        newView.selfieGuide = self;
        newView.selfieFaceImage = faceImage;
        //newView.idSuccess = self.idSuccess;
        [nav pushViewController:newView animated:YES];
        
        UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        [rootViewController presentViewController:nav animated:YES completion:nil];
    });
}

- (void) failedCase:(componentCallDirectly)callFlag {
    
    dispatch_async(dispatch_get_main_queue(), ^{
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:VFY_MAIN_STORYBOARD bundle:self.bundlePath];
        UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:VFY_NAVIGATION_IDFAILGUIDE_STORYBOARD];
        [self setNavigationBoder:nav];
        [self setNavigationAppearance];
        VFYIDFailGuideWrapper *vc = [storyboard instantiateViewControllerWithIdentifier:VFY_IDFAILGUIDE_STORYBOARD];
        vc.idGuide = self;
        vc.callDirectlyFlag = callFlag;
        [nav pushViewController:vc animated:YES];
        
        UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        [rootViewController presentViewController:nav animated:YES completion:nil];
    });
}

- (void) setNavigationBoder:(UINavigationController *) navigation {
    [navigation.navigationBar.layer setShadowColor: [Utilities colorFromColorString:VFY_NAVIGATION_BODER].CGColor];
    [navigation.navigationBar.layer setShadowOffset: CGSizeMake(0, 2)];
    [navigation.navigationBar.layer setShadowRadius:1.0];
    [navigation.navigationBar.layer setShadowOpacity: 0.7];
}

- (void) setNavigationAppearance {
  [[UINavigationBar appearance] setBarTintColor:[Utilities colorFromColorString:[self.sharedInstance headerColor]]]; //header background
  [[UINavigationBar appearance] setTintColor:[Utilities colorFromColorString:[self.sharedInstance headerTextColor]]]; //back button
  [[UINavigationBar appearance] setTranslucent:false];
  NSDictionary *attributes = @{ NSForegroundColorAttributeName : [Utilities colorFromColorString:[self.sharedInstance headerTextColor]], NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Bold" size:17] }; //Title text color
  [[UINavigationBar appearance] setTitleTextAttributes:attributes];
}



- (void) closeParentView:(NSDictionary*)response {
    [[self currentController] willMoveToParentViewController:nil];  // 1
    [[self currentController].view removeFromSuperview];
    [[self currentController] removeFromParentViewController];//this line is updated as view is removed from parent view controller instead of its viewcontroller is removed from parentViewController
    
    NSMutableArray *jsonResults;
    
    if(response != (NSDictionary*)[NSNull null]) {
        jsonResults = [[NSMutableArray alloc] init];
        NSMutableDictionary *serializeObj = [[NSMutableDictionary alloc] init];
        if([response isKindOfClass:[ResultModelIdFail class]]) {
            serializeObj  =(NSMutableDictionary*)[self serializeIdFailedResult:response];
        } else if([response isKindOfClass:[VFYIDSuccess class]]) {
            serializeObj  =(NSMutableDictionary*)[self serializeIdResult:response];
        } else if([response isKindOfClass:[ResultModelCard class]]) {
            serializeObj  =(NSMutableDictionary*)[self serializeCardResult:response];
        } else if([response isKindOfClass:[ResultModelSelfie class]]){
            serializeObj  =(NSMutableDictionary*)[self serializeSelfieResult:response];
        }
        [jsonResults addObject:serializeObj];
    }
  
  NSLog(@"Final Result :: %@", jsonResults);
  
    if(jsonResults != nil)
      self.promiseResolve(jsonResults);
    else {
      NSError *error = [NSError errorWithDomain:MBErrorDomain
                                           code:-100
                                       userInfo:nil];
      self.promiseReject(kStatusScanCanceled, @"Scanning has been canceled with not any data", error);
    }
    
    self.currentController = nil;
    self.scanningViewController = nil;
    self.recognizerCollection = nil;
}



- (void)setCustomSetting:(NSDictionary*) jsonCustomSetting SharedInstanced:(VFYVerifyApp *) sharedInstanced {
    if([jsonCustomSetting objectForKey:@"headerBackgroundColor"] != nil) {
        if([[jsonCustomSetting objectForKey:@"headerBackgroundColor"] length] == 7) {
            [sharedInstanced setHeaderColor:[jsonCustomSetting objectForKey:@"headerBackgroundColor"]];
        }
    }
    if([jsonCustomSetting objectForKey:@"headerTextColor"] != nil) {
        if([[jsonCustomSetting objectForKey:@"headerTextColor"] length] == 7) {
            [sharedInstanced setHeaderTextColor:[jsonCustomSetting objectForKey:@"headerTextColor"]];
        }
    }
    if([jsonCustomSetting objectForKey:@"bodyTextColor"] != nil) {
        if([[jsonCustomSetting objectForKey:@"bodyTextColor"] length] == 7) {
            [sharedInstanced setBodyTextColor:[jsonCustomSetting objectForKey:@"bodyTextColor"]];
        }
    }
    if([jsonCustomSetting objectForKey:@"bodyBackgroundColor"] != nil) {
        if([[jsonCustomSetting objectForKey:@"bodyBackgroundColor"] length] == 7) {
            [sharedInstanced setBodyColor:[jsonCustomSetting objectForKey:@"bodyBackgroundColor"]];
        }
    }
    if([jsonCustomSetting objectForKey:@"bodyTitleColor"] != nil) {
        if([[jsonCustomSetting objectForKey:@"bodyTitleColor"] length] == 7) {
            [sharedInstanced setBodyTitleColor:[jsonCustomSetting objectForKey:@"bodyTitleColor"]];
        }
    }
    if([jsonCustomSetting objectForKey:@"accountOwnerFirstName"] != nil) {
        NSString *accFirst = [jsonCustomSetting objectForKey:@"accountOwnerFirstName"];
        accFirst = [accFirst stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        [sharedInstanced setAccountOwnerFirstName:accFirst];
    }
    if([jsonCustomSetting objectForKey:@"accountOwnerLastName"] != nil) {
        NSString *acclast = [jsonCustomSetting objectForKey:@"accountOwnerLastName"];
        acclast = [acclast stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        [sharedInstanced setAccountOwnerLastName:acclast];
    }
    if([jsonCustomSetting objectForKey:@"cardOwnerFirstName"] != nil) {
        NSString *crdFirst = [jsonCustomSetting objectForKey:@"cardOwnerFirstName"];
        crdFirst = [crdFirst stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        [sharedInstanced setCardOwnerFirstName:crdFirst];
    }
    if([jsonCustomSetting objectForKey:@"cardOwnerLastName"] != nil) {
        NSString *crdLast = [jsonCustomSetting objectForKey:@"cardOwnerLastName"];
        crdLast = [crdLast stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        [sharedInstanced setCardOwnerLastName:crdLast];
    }
    if([jsonCustomSetting objectForKey:@"language"] != nil) {
        if([[jsonCustomSetting objectForKey:@"language"] length]>0){
            [sharedInstanced setLanguage:[Utilities checkLanguageSupported:[jsonCustomSetting objectForKey:@"language"]]];
        }
    }
    if([jsonCustomSetting objectForKey:@"headerTitleText"] != nil) {
        [sharedInstanced setHeaderTitleText:[jsonCustomSetting objectForKey:@"headerTitleText"]];
    }
    if([jsonCustomSetting objectForKey:@"headerTitleImage"] != nil) {
        [sharedInstanced setHeaderTitleImage:[jsonCustomSetting objectForKey:@"headerTitleImage"]];
    }
    if([jsonCustomSetting objectForKey:@"geoLanguage"] != nil){
        BOOL geolanguage = [[jsonCustomSetting objectForKey:@"geoLanguage"] boolValue];
        [sharedInstanced setGeoLanguage:geolanguage];
    }
    if([jsonCustomSetting objectForKey:@"buttonBackgroundColor"] != nil) {
        [sharedInstanced setButtonBackgroundColor:[jsonCustomSetting objectForKey:@"buttonBackgroundColor"]];
    }
    if([jsonCustomSetting objectForKey:@"buttonBorderColor"] != nil) {
        [sharedInstanced setButtonBorderColor:[jsonCustomSetting objectForKey:@"buttonBorderColor"]];
    }
    if([jsonCustomSetting objectForKey:@"buttonTextColor"] != nil) {
        [sharedInstanced setButtonTextColor:[jsonCustomSetting objectForKey:@"buttonTextColor"]];
    }
    if([jsonCustomSetting objectForKey:@"scanType"] != nil) {
        [sharedInstanced setScanType:[jsonCustomSetting objectForKey:@"scanType"]];
    }
    if([jsonCustomSetting objectForKey:@"allowNameSuggestion"] != nil){
        BOOL suggest = [[jsonCustomSetting objectForKey:@"allowNameSuggestion"] boolValue];
        [sharedInstanced setSuggestionValidation:suggest];
    }
    if([jsonCustomSetting objectForKey:@"requestId"] != nil){
        [sharedInstanced setRequestId:[jsonCustomSetting objectForKey:@"requestId"]];
    }
    if([jsonCustomSetting objectForKey:@"minimumAgeLimit"] != nil) {
        [sharedInstanced setMinimumAgeLimit:[jsonCustomSetting objectForKey:@"minimumAgeLimit"]];
    }
    if([jsonCustomSetting objectForKey:@"reviewPage"] != nil){
        BOOL reviewPage = [[jsonCustomSetting objectForKey:@"reviewPage"] boolValue];
        [sharedInstanced setReviewPage:reviewPage];
    }
}



- (NSDictionary*) serializeIdFailedResult:(id) idFail {
    ResultModelIdFail *failId = (ResultModelIdFail*)idFail;
    //NSMutableDictionary *idFailResult = (NSMutableDictionary*)idFail;
    NSMutableDictionary* jsonResult = [[NSMutableDictionary alloc] init];
    
    [jsonResult setValue:[NSNumber numberWithBool:FALSE] forKey:@"isCard"];
    [jsonResult setValue:[NSNumber numberWithBool:TRUE] forKey:@"isID"];
    [jsonResult setValue:[NSNumber numberWithBool:FALSE] forKey:@"isSuccessful"];
    
    [jsonResult setValue:failId.country forKey:VFY_FAILRESPONSE_COUNTRY];
    [jsonResult setValue:failId.documenttype forKey:VFY_FAILRESPONSE_DOCUMENTTYPE];
    [jsonResult setValue:failId.frontimage forKey:VFY_FAILRESPONSE_FRONTIMAGE];
    [jsonResult setValue:failId.backimage forKey:VFY_FAILRESPONSE_BACKIMAGE];
    
    [jsonResult setValue:@"ios" forKey:@"deviceType"];
    [jsonResult setValue:[VFYDeviceTypes deviceModelName] forKey:@"deviceModel"];
    [jsonResult setValue:[VFYDeviceTypes deviceModelOS] forKey:@"deviceOsVersion"];

    return jsonResult;
}

- (NSDictionary *) serializeIdResult:(id) idSuccess {
    VFYIDSuccess *success = (VFYIDSuccess*)idSuccess;
    NSMutableDictionary* jsonResult = [[NSMutableDictionary alloc] init];
    
    [jsonResult setValue:[NSNumber numberWithBool:success.isCard] forKey:@"isCard"];
    [jsonResult setValue:[NSNumber numberWithBool:success.isID] forKey:@"isID"];
    [jsonResult setValue:[NSNumber numberWithBool:success.isSuccessful] forKey:@"isSuccessful"];
    
    [jsonResult setValue:success.extractedFirstName forKey:@"extractedFirstName"];
    [jsonResult setValue:[NSNumber numberWithBool:success.firstNameEditedFlag] forKey:@"firstNameEditedFlag"];
    [jsonResult setValue:success.editedFirstName forKey:@"editedFirstName"];
    
    [jsonResult setValue:success.extractedLastName forKey:@"extractedLastName"];
    [jsonResult setValue:[NSNumber numberWithBool:success.lastNameEditedFlag] forKey:@"lastNameEditedFlag"];
    [jsonResult setValue:success.editedLastName forKey:@"editedFirstName"];
    
    [jsonResult setValue:success.extractedGender forKey:@"extractedGender"];
    [jsonResult setValue:[NSNumber numberWithBool:success.genderEditedFlag] forKey:@"genderEditedFlag"];
    [jsonResult setValue:success.editedGender forKey:@"editedGender"];
    
    [jsonResult setValue:success.extractedIdDocumentNumber forKey:@"extractedIdDocumentNumber"];
    [jsonResult setValue:[NSNumber numberWithBool:success.idDocumentNumberEditedFlag] forKey:@"idDocumentNumberEditedFlag"];
    [jsonResult setValue:success.editedIdDocumentNumber forKey:@"editedIdDocumentNumber"];
    [jsonResult setValue:[NSNumber numberWithInteger:success.documentNumberScore] forKey:@"documentNumberScore"];
    
    [jsonResult setValue:success.extractedDocumentType forKey:@"extractedDocumentType"];
    [jsonResult setValue:[NSNumber numberWithBool:success.documentTypeEditedFlag] forKey:@"documentTypeEditedFlag"];
    [jsonResult setValue:success.editedDocumentType forKey:@"editedDocumentType"];
    
    [jsonResult setValue:success.extractedDateOfBirth forKey:@"extractedDateOfBirth"];
    [jsonResult setValue:[NSNumber numberWithBool:success.dateOfBirthEditedFlag] forKey:@"dateOfBirthEditedFlag"];
    [jsonResult setValue:success.editedDateOfBirth forKey:@"editedDateOfBirth"];
    [jsonResult setValue:[NSNumber numberWithInteger:success.dateOfBirthScore] forKey:@"dateOfBirthScore"];
    
    [jsonResult setValue:success.extractedDateOfExpire forKey:@"extractedDateOfExpire"];
    [jsonResult setValue:[NSNumber numberWithBool:success.dateOfExpireEditedFlag] forKey:@"dateOfExpireEditedFlag"];
    [jsonResult setValue:success.editedDateOfExpire forKey:@"editedDateOfExpire"];
    
    [jsonResult setValue:success.extractedNation forKey:@"extractedNation"];
    [jsonResult setValue:[NSNumber numberWithBool:success.nationEditedFlag] forKey:@"nationEditedFlag"];
    [jsonResult setValue:success.editedNation forKey:@"editedNation"];
    
    [jsonResult setValue:success.extractedAddress forKey:@"extractedAddress"];
    [jsonResult setValue:[NSNumber numberWithBool:success.addressEditedFlag] forKey:@"addressEditedFlag"];
    [jsonResult setValue:success.editedAddress forKey:@"editedAddress"];
    
    [jsonResult setValue:success.extractedIssuer forKey:@"extractedIssuer"];
    [jsonResult setValue:[NSNumber numberWithBool:success.issuerEditedFlag] forKey:@"issuerEditedFlag"];
    [jsonResult setValue:success.editedIssuer forKey:@"editedIssuer"];
    
    [jsonResult setValue:success.fullName forKey:@"fullName"];
    [jsonResult setValue:success.faceImage forKey:@"faceImage"];
    [jsonResult setValue:success.documentFrontImage forKey:@"documentFrontImage"];
    [jsonResult setValue:success.documentBackImage forKey:@"documentBackImage"];
    
    [jsonResult setValue:success.selfieCompareMessage forKey:@"selfieCompareMessage"];
    [jsonResult setValue:[NSNumber numberWithBool:success.selfieCompareFlag] forKey:@"selfieCompareFlag"];
    //[jsonResult setValue:[NSNumber numberWithInteger:success.selfieConfidenceScore] forKey:@"selfieConfidenceScore"];
    [jsonResult setValue:success.selfieConfidenceScore forKey:@"selfieConfidenceScore"];
    
    [jsonResult setValue:success.deviceType forKey:@"deviceType"];
    [jsonResult setValue:success.deviceModel forKey:@"deviceModel"];
    [jsonResult setValue:success.deviceOsVersion forKey:@"deviceOsVersion"];
    
    return jsonResult;
}

- (NSDictionary *) serializeCardResult:(id) cardSuccess {
    ResultModelCard *success = (ResultModelCard*)cardSuccess;
    NSMutableDictionary* jsonResult = [[NSMutableDictionary alloc] init];
    
    [jsonResult setValue:[NSNumber numberWithBool:success.isCard] forKey:@"isCard"];
    [jsonResult setValue:[NSNumber numberWithBool:success.isID] forKey:@"isID"];
    [jsonResult setValue:[NSNumber numberWithBool:success.isSuccessful] forKey:@"isSuccessful"];
    
    [jsonResult setValue:success.extractedCardHolderName forKey:@"extractedCardHolderName"];
    [jsonResult setValue:[NSNumber numberWithBool:success.cardHolderNameEditedFlag] forKey:@"cardHolderNameEditedFlag"];
    [jsonResult setValue:success.editedCardHolderName forKey:@"editedCardHolderName"];
    [jsonResult setValue:[NSNumber numberWithInteger:success.cardHolderNameScore] forKey:@"cardHolderNameScore"];
    
    [jsonResult setValue:success.extractedCardNumber forKey:@"extractedCardNumber"];
    [jsonResult setValue:[NSNumber numberWithBool:success.cardNumberEditedFlag] forKey:@"cardNumberEditedFlag"];
    [jsonResult setValue:success.editedCardNumber forKey:@"editedCardNumber"];
    [jsonResult setValue:[NSNumber numberWithInteger:success.cardNumberScore] forKey:@"cardNumberScore"];
    
    [jsonResult setValue:success.extractedDateOfExpire forKey:@"extractedDateOfExpire"];
    [jsonResult setValue:[NSNumber numberWithBool:success.dateOfExpireEditedFlag] forKey:@"dateOfExpireEditedFlag"];
    [jsonResult setValue:success.editedDateOfExpire forKey:@"editedDateOfExpire"];
    [jsonResult setValue:[NSNumber numberWithInteger:success.dateOfExpireScore] forKey:@"dateOfExpireScore"];
    
    [jsonResult setValue:success.cvv forKey:@"cvv"];
    //[jsonResult setValue:[Utilities encodeToBase64String:success.cardImage] forKey:@"cardImage"];
    if(success.documentFrontImage != nil){
        [jsonResult setValue:success.documentFrontImage forKey:@"documentFrontImage"];
    }
    if(success.documentBackImage != nil){
        [jsonResult setValue:success.documentBackImage forKey:@"documentBackImage"];
    }
    [jsonResult setValue:success.deviceType forKey:@"deviceType"];
    [jsonResult setValue:success.deviceModel forKey:@"deviceModel"];
    [jsonResult setValue:success.deviceOsVersion forKey:@"deviceOsVersion"];
    return jsonResult;
}

-(NSDictionary *) serializeSelfieResult:(id) selfieSuccess {
    ResultModelSelfie *success = (ResultModelSelfie*)selfieSuccess;
    NSMutableDictionary* jsonResult = [[NSMutableDictionary alloc] init];
    [jsonResult setValue:success.selfieCompareMessage forKey:@"selfieCompareMessage"];
    [jsonResult setValue:[NSNumber numberWithBool:success.selfieCompareFlag] forKey:@"selfieCompareFlag"];
    [jsonResult setValue:success.selfieConfidenceScore forKey:@"selfieConfidenceScore"];
    return jsonResult;
}



#pragma MARK - Deletegate Event

- (void) callFrom:(NSString *)controllerName {
  NSLog(@"======= callFrom =============");
  /*
  [self callScanner];
    //[self successCase:nil];
    //[self failedCase:InDirectly];
    //[self cardCase];
  */
}

- (void) callClose:(comeFromViewController)controllerName {
  
  if(controllerName == IDFailedGuideWrapper){
     /* Uncomment this when shared instance object is used */
     //self.currentController = self.idGuiWrapper;
     //[[self viewController] dismissViewControllerAnimated:YES completion:nil];
     //NSDictionary *responseDicts = self.sharedInstance.failedResponse;
     //[self closeParentView:responseDicts];
  } else if(controllerName == CardSuccessComplete){
     self.currentController = self.cardGuiWrapper; //[[self viewController] dismissViewControllerAnimated:YES completion:nil];
     [self closeParentView:(NSDictionary*)[NSNull null]];
  } else if(controllerName == IDSuccessWrapper || controllerName == IDFailedGuideWrapperClose || controllerName == CardSuccessClose || controllerName == SelfieGuideWrapperClose) {
     //[[self viewController] dismissViewControllerAnimated:YES completion:nil];
     [self returnCancelFalse];
  } else {
     self.currentController = self.idGuiWrapper;
    UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
    [rootViewController dismissViewControllerAnimated:YES completion:nil];
     [self closeParentView:(NSDictionary*)[NSNull null]];
  }/*else if(controllerName == IDSuccessWrapper || controllerName == IDFailedGuideWrapperClose) {
     //[[self viewController] dismissViewControllerAnimated:YES completion:nil]; } */
}

- (void) callClose:(comeFromViewController)controllerName PassValue:(id)passValue {
  
   if(controllerName == IDSuccessComplete){
       self.currentController = self.idGuiWrapper;
       UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
       [rootViewController dismissViewControllerAnimated:YES completion:nil];
       [self closeParentView:passValue];
   } else if(controllerName == CardSuccessComplete || controllerName == SelfieGuideWrapperComplete){
       UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
       [rootViewController dismissViewControllerAnimated:YES completion:nil];
       [self closeParentView:passValue];
   } else if(controllerName == IDFailedGuideWrapper){
       self.currentController = self.idGuiWrapper;
       UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
       [rootViewController dismissViewControllerAnimated:YES completion:nil];
       [self closeParentView:passValue];
   }
  
}

- (void) callBackFromPopupClose:(popupCallFromMethod)methodName PassValue:(id)passValue {
  NSLog(@"======= callBackFromPopupClose PassValue =============");
}

/**
  Call camera for scanning
*/
- (void) callScanner {
  NSLog(@"======= callScanner =============");
    
  /*
    self.auditScanDuration = CACurrentMediaTime();
    NSDictionary *jsonOverlaySettings = [self sanitizeDictionary:[self.lastCommand argumentAtIndex:0]];
    NSDictionary *jsonRecognizerCollection = [self sanitizeDictionary:[self.lastCommand argumentAtIndex:1]];
    NSDictionary *jsonLicenses = [self sanitizeDictionary:[self.lastCommand argumentAtIndex:2]];

    [self setLicense:jsonLicenses];

    [[MBMicroblinkApp instance] setLanguage:[self.sharedInstance language]];
    
    self.recognizerCollection = [[MBRecognizerSerializers sharedInstance] deserializeRecognizerCollection:jsonRecognizerCollection];
 
    // create overlay VC
    MBOverlayViewController *overlayVC = [[MBOverlaySettingsSerializers sharedInstance] createOverlayViewController:jsonOverlaySettings recognizerCollection:self.recognizerCollection delegate:self];
    UIViewController<MBRecognizerRunnerViewController>* recognizerRunnerViewController = [MBViewControllerFactory recognizerRunnerViewControllerWithOverlayViewController:overlayVC];

    self.scanningViewController = recognizerRunnerViewController;
    [recognizerRunnerViewController setModalPresentationStyle:UIModalPresentationOverFullScreen];
    CATransition *transition = [CATransition animation];
    transition.duration = 0.35;
    transition.timingFunction =
    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionMoveIn;
    transition.subtype = kCATransitionFromRight;
    // NSLog(@"%s: self.view.window=%@", _func_, self.view.window);
    UIView *containerView = [self viewController].view.window;
    [containerView.layer addAnimation:transition forKey:nil];
    [[self viewController] presentViewController:recognizerRunnerViewController animated:NO completion:nil];
  */
}


- (void) returnCancelFalse {
  
  UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
  [rootViewController dismissViewControllerAnimated:YES completion:nil];
  self.recognizerCollection = nil;
  self.scanningViewController = nil;
  NSError *error = [NSError errorWithDomain:MBErrorDomain
                                       code:-58
                                   userInfo:nil];
  self.promiseReject(kStatusScanCanceled, @"Scanning has been canceled from returnCancelFalse", error);

  self.promiseResolve = nil;
  self.promiseReject = nil;
}

@end
