
#import "CDVIndigitall.h"
#import <Indigitall/Indigitall.h>
#import <Indigitall/INPushConfig.h>
#import <Indigitall/IndigitallInApp.h>
#import <Indigitall/INInAppUtils.h>
#import "CDVINDefaults.h"
#import "CDVIndigitallParse.h"

@implementation CDVIndigitall

@synthesize notificationCallbackId;
@synthesize tokenRefreshCallbackId;
@synthesize getOnIndigitallPushCallbackId;

static CDVIndigitall *cdvIndigitallPlugin;

+ (CDVIndigitall *) cdvIndigitallPlugin {
    return cdvIndigitallPlugin;
}

- (void) requestPushPermissions: (CDVInvokedUrlCommand *)command {
    [self.commandDelegate runInBackground:^{
        [[[INPermissionHandler alloc]init]askUserForNotificationPermission];
    }];
}

- (void) getPushPermissionStatus: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        @try{
            if (@available(iOS 10.0, *)){
                UNUserNotificationCenter *current = [UNUserNotificationCenter  currentNotificationCenter];
                [current getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
                    if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined){
                        [self successWithString:@"notDeterminated" command:command];
                    }else if (settings.authorizationStatus == UNAuthorizationStatusDenied){
                        [self successWithString:@"denied" command:command];
                    }else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized){
                        [self successWithString:@"granted" command:command];
                    }
                }];
            }
        } @catch (NSException *exception) {
            [self failedWithCommand:command];
        }
    }];
}

- (void) initialize: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
    
        cdvIndigitallPlugin = self;
        NSDictionary *params = command.arguments.firstObject;
        NSString *appKey = params[@"appKey"];

        NSLog(@"params: %@",params);
    
        INPushConfig *config = [[INPushConfig alloc]init];
        config.appKey = appKey;

        config.pushPermissionMode = automatic;
        if (params[@"autoRequestPushPermission"]) {
            BOOL result = [params[@"autoRequestPushPermission"]boolValue];
            if (!result)  config.pushPermissionMode = manual;
        }

        config.locationPermissionMode = automatic;
        if (params[@"requestLocation"]){
            BOOL result = [params[@"requestLocation"]boolValue];
            if (!result) config.locationPermissionMode = manual;
        }

        if (params[@"avoidCypher"]){
            config.avoidCypher = [params[@"avoidCypher"]boolValue];
        }
        
        if (params[@"wifiFilterEnabled"]){
            config.wifiFilterEnabled = [params[@"wifiFilterEnabled"]boolValue];
        }

        if (params[@"disabledPushService"]) [config setDisabledPushService:params[@"disabledPushService"]];
        if (params[@"timeoutRequestsInMilliseconds"] != nil && params[@"timeoutRequestsInMilliseconds"] != 0) [config setTimeoutRequestsInMilliseconds:[params[@"timeoutRequestsInMilliseconds"]intValue]];
        if (params[@"backgroundRequestsDisabled"]) [config setBackgroundRequestsDisabled:[params[@"backgroundRequestsDisabled"]boolValue]];
        
        if (params[@"urlDeviceApi"]) config.domain = params[@"urlDeviceApi"];
        //if (params[@"urlInAppApi"]) config.domainInApp = params[@"urlInAppApi"];
        if (params[@"urlInboxApi"]) config.domainInbox = params[@"urlInboxApi"];

        NSNumber *logLevelRawValue = params[@"logLevel"];
        if (logLevelRawValue != nil) {
            config.debugMode = (INLogLevel)[logLevelRawValue unsignedIntValue];
        }
         
        [INDefaults setProductName:params[@"productName"]];
        [INDefaults setProductVersion:params[@"productVersion"]];
        // [config setProductName:params[@"productName"]];
        // [config setProductVersion:params[@"productVersion"]];
                
        [Indigitall askNotificationPermission];
        dispatch_async(dispatch_get_main_queue(), ^{
            [Indigitall initializeWithConfig:config onIndigitallInitialized:^(NSArray<INPermissions *> * _Nonnull permissions, INDevice * _Nonnull device) {
                [self successWithDevice:device command:command];
                } onErrorInitialized:^(INError * _Nonnull onError) {
                            [self failedWithCommand:command];
                }];
         });
    }];
}

- (void) packageName:(CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
        CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:bundleIdentifier];
        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
        
    }];
}

- (void) deviceGet: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        [Indigitall getDeviceWithOnSuccess:^(INDevice * _Nonnull device) {
            [self successWithDevice:device command:command];
        } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
        }];
    }];
}

- (void) deviceEnable: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        [Indigitall enableDeviceWithOnSuccess:^(INDevice * _Nonnull device) {
             [self successWithDevice:device command:command];
        } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
        }];
    }];
}

- (void) deviceDisable: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        [Indigitall disableDeviceWithOnSuccess:^(INDevice * _Nonnull device) {
             [self successWithDevice:device command:command];
        } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
        }];
    }];
}

- (void) topicsList: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        [Indigitall topicsListWithOnSuccess:^(NSArray<INTopic *> * _Nonnull topics) {
            [self successWithTopic:topics command:command];
        } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
        }];
    }];
}

- (void) topicsSubscribe: (CDVInvokedUrlCommand *)command{
    id object = [command.arguments objectAtIndex:0];
    if (![object isKindOfClass:[NSString class]]){
      NSArray<INTopic *>* params = command.arguments;
        NSMutableArray<INTopic *>* topicsList = [[NSMutableArray alloc]init];
           for (int i = 0; i < params.count; i++) {
               INTopic *topic = [[INTopic alloc]init:[params[i] mutableCopy]];
               topicsList[i] = topic;
           }
      [self.commandDelegate runInBackground:^{
          [Indigitall topicsSubscribeWithTopic:topicsList onSuccess:^(NSArray<INTopic *> * _Nonnull topics) {
              [self successWithTopic:topics command:command];
          } onError:^(INError * _Nonnull error) {
              [self failedWithCommand:command];
          }];
           
       }];
    }else if ([object isKindOfClass:[NSString class]]){
         NSArray<NSString *>* params = command.arguments;
         [self.commandDelegate runInBackground:^{
             [Indigitall topicsSubscribeWithArrayString:params onSuccess:^(NSArray<INTopic *> * _Nonnull topics) {
                 [self successWithTopic:topics command:command];
             } onError:^(INError * _Nonnull error) {
                 [self failedWithCommand:command];
             }];
          }];
    }else{
        [self failedWithCommand:command];
    }
}

- (void) topicsUnsubscribe: (CDVInvokedUrlCommand *)command{
    id object = [command.arguments objectAtIndex:0];
    if (![object isKindOfClass:[NSString class]]){
       NSArray<INTopic *>* params = command.arguments;
       NSMutableArray<INTopic *>* topicsList = [[NSMutableArray alloc]init];
          for (int i = 0; i < params.count; i++) {
              INTopic *topic = [[INTopic alloc]init:[params[i] mutableCopy]];
              topicsList[i] = topic;
          }
       [self.commandDelegate runInBackground:^{
           [Indigitall topicsUnSubscribeWithTopic:topicsList onSuccess:^(NSArray<INTopic *> * _Nonnull topics) {
               [self successWithTopic:topics command:command];
           } onError:^(INError * _Nonnull error) {
               [self failedWithCommand:command];
           }];
            
        }];
    }else if ([object isKindOfClass:[NSString class]]){
       NSArray<NSString *>* params = command.arguments;
       [self.commandDelegate runInBackground:^{
           [Indigitall topicsUnSubscribeWithArrayString:params onSuccess:^(NSArray<INTopic *> * _Nonnull topics) {
               [self successWithTopic:topics command:command];
           } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
           }];
            
        }];
    }else{
         [self failedWithCommand:command];
    }
}

- (void) setExternalCode: (CDVInvokedUrlCommand *)command{
    NSString *params = command.arguments.firstObject[@"externalCode"];
     if (params != nil){
        [self.commandDelegate runInBackground:^{
            [Indigitall setExternalCode:params onSuccess:^(INDevice * _Nonnull device) {
                [self successWithDevice:device command:command];
            } onError:^(INError * _Nonnull error) {
                [self failedWithCommand:command];
            }];
        }];
     }else{
          [self failedWithCommand:command];
     }
}

- (void) sendCustomEvent: (CDVInvokedUrlCommand *)command{
    NSDictionary *params = command.arguments.firstObject;
    NSString *event;
    NSDictionary *customData;
    NSString *eventId;
    NSString *eventAt;
     if (params[@"event"]) event = params[@"event"];
     if (params[@"customData"]) customData = params[@"customData"];
     if (params[@"eventId"]) eventId = params[@"eventId"];
     if (params[@"eventAt"]) eventAt = params[@"eventAt"];
    if (params != nil){
        [self.commandDelegate runInBackground:^{
            [Indigitall sendCustomEvent:event eventId:eventId eventAt:eventAt customData:customData onSuccess:^{
                [self successWithCommand: command];
            } onError:^(INError * _Nonnull error) {
                [self failedWithCommand:command];
            }];
           
        }];
    }else{
         [self failedWithCommand:command];
    }
}

- (void) getPush: (CDVInvokedUrlCommand *)command{
    [[NSNotificationCenter defaultCenter] addObserverForName:@"IndigitallHandleWithNotificationPush" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        if ([CDVINDefaults getIndigitallHandleWithNotificationPush] != nil) {
//            if ((UIWebView *)self.webView != nil) [(UIWebView *)self.webView reload];
            if ((WKWebView *)self.webView != nil) {
                NSString *urlGetPushMethod = [CDVINDefaults getGetPushMethodUrl];
                if (urlGetPushMethod != nil) [(WKWebView*)self.webView loadFileURL:[NSURL URLWithString:urlGetPushMethod] allowingReadAccessToURL:[NSURL URLWithString:urlGetPushMethod]];
               //
            }
        }
    }];
    if ((WKWebView *)self.webView != nil) [CDVINDefaults setGetPushMethodUrl:[[(WKWebView *)self.webView URL] absoluteString]];
    [self.commandDelegate runInBackground:^{
        NSDictionary *dictionaryPush = [CDVINDefaults getIndigitallHandleWithNotificationPush];
         if (dictionaryPush != nil) {             
             CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionaryPush];
             [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
             [CDVINDefaults setIndigitallHandleWithNotificationPush:nil];
         }else{
             [self failedWithString:@"No push was getting" command:command];
         }
    }];
}

-(void) onIndigitallGetPush:(CDVInvokedUrlCommand *)command {
    self.getOnIndigitallPushCallbackId = command.callbackId;
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *url = [[(WKWebView *)self.webView URL] absoluteString];
        NSString *urlGetPushMethod = [CDVINDefaults getGetPushMethodUrl];
        if (urlGetPushMethod == nil) {
            [CDVINDefaults setGetNativePushMethodUrl:url];
        }
        if ([CDVINDefaults getIndigitallHandleWithNotificationPush] != nil) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[CDVINDefaults getIndigitallHandleWithNotificationPush]];
            [pluginResult setKeepCallbackAsBool:YES];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:self.getOnIndigitallPushCallbackId];
            [CDVINDefaults setIndigitallHandleWithNotificationPush:nil];
        }
    });
}

- (void) onHandleNotificationTap: (NSDictionary*)userInfo {
    [self.commandDelegate runInBackground:^{
        if (self.getOnIndigitallPushCallbackId != nil) {
            NSString *urlGetPushMethod = [CDVINDefaults getGetPushMethodUrl];
            NSString *urlGetNativePushMethod = [CDVINDefaults getGetNativePushMethodUrl];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (urlGetNativePushMethod != nil && ![[[(WKWebView *)self.webView URL] absoluteString] isEqual:urlGetNativePushMethod]){
                    [(WKWebView*)self.webView loadFileURL:[NSURL URLWithString:urlGetNativePushMethod] allowingReadAccessToURL:[NSURL URLWithString:urlGetNativePushMethod]];
                } else if (urlGetPushMethod != nil) {
                    NSString *completUrl = [NSString stringWithFormat:@"%@www/%@",[[[NSBundle mainBundle]bundleURL]absoluteString],urlGetPushMethod];
                    if (![[[(WKWebView *)self.webView URL] absoluteString] isEqual:completUrl]){
                        [(WKWebView*)self.webView loadFileURL:[NSURL URLWithString:completUrl] allowingReadAccessToURL:[NSURL URLWithString:completUrl]];
                    }
                }
            });
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:userInfo];
            [pluginResult setKeepCallbackAsBool:YES];
            //[CDVINDefaults setIndigitallHandleWithNotificationPush:nil];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:self.getOnIndigitallPushCallbackId];
        }
    }];
}

- (void) setDefaultViewUrl:(CDVInvokedUrlCommand *)command {
    NSString *params = command.arguments.firstObject;
    if (params != nil) {
        [CDVINDefaults setGetPushMethodUrl:params];
        [CDVINDefaults setGetNativePushMethodUrl:nil];
    }
}

- (void) clearViewUrl:(CDVInvokedUrlCommand *)command {
    [CDVINDefaults setGetPushMethodUrl:nil];
    [CDVINDefaults setGetNativePushMethodUrl:nil];
}

- (void) onMessageReceived: (CDVInvokedUrlCommand *)command {
    self.notificationCallbackId = command.callbackId;
}

- (void)sendNotification:(NSDictionary*)userInfo {
    [self.commandDelegate runInBackground:^{
        if (self.notificationCallbackId != nil) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:userInfo];
            [pluginResult setKeepCallbackAsBool:YES];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:self.notificationCallbackId];
        }
    }];
}

- (void) getToken: (CDVInvokedUrlCommand *)command {
    [self.commandDelegate runInBackground:^{
        NSString * token = [INPushDefaults getPushToken];
        if (token != nil) {
            [self successWithString:token  command:command];
        } else {
            self.tokenRefreshCallbackId = command.callbackId;
            //[self failedWithCommand:command];
        }
    }];
}

- (void)sendToken:(NSData*)token {
    if (self.tokenRefreshCallbackId != nil) {
        NSUInteger length = token.length;
        if (length == 0) {
            return;
        }
        const unsigned char *buffer = token.bytes;
        NSMutableString *pushToken  = [NSMutableString stringWithCapacity:(length * 2)];
        for (int i = 0; i < length; ++i) {
            [pushToken appendFormat:@"%02x", buffer[i]];
        }
        [self.commandDelegate runInBackground:^{
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:pushToken];
            [pluginResult setKeepCallbackAsBool:YES];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:self.tokenRefreshCallbackId];
        }];
    }
}

- (void) isIndigitallPushNotification: (CDVInvokedUrlCommand *)command {
    NSDictionary *params = command.arguments.firstObject;
    [self.commandDelegate runInBackground:^{
        if (params != nil) {
            INPush *push = [INNotificationHandler getPushObject:params];
            if (push != nil && push.appKey != nil) {
                [self successWithCommand:command];
            } else {
                [self failedWithCommand:command];
            }
        }
    }];
}

- (void) isPushSecure: (CDVInvokedUrlCommand *)command {
    NSDictionary *params = command.arguments.firstObject;
    [self.commandDelegate runInBackground:^{
        if (params != nil) {
            INPush *push = [INNotificationHandler getPushObject:params];
            if (push != nil &&
                push.sendEventAck) {
                [self successWithCommand:command];
                BOOL isPushSecure = false;
                if ([INDefaults getSecureSendingEnabled]) isPushSecure = true;
                INRequestEvent *event = [[INRequestEvent alloc]initWithPushEvent:push isPushSecure:isPushSecure];
                [INAPIClient eventPushReceived:event];
            } else {
                [self failedWithCommand:command];            
            }
        }
    }];
}

- (void) logIn: (CDVInvokedUrlCommand *)command{
    NSString *params = command.arguments.firstObject;
     if (params != nil){
        [self.commandDelegate runInBackground:^{
            [Indigitall logInWithId:params onSuccess:^(INDevice * _Nonnull device) {
                [self successWithDevice:device command:command];
            } onError:^(INError * _Nonnull error) {
                [self failedWithCommand:command];
            }];
        }];
     }else{
          [self failedWithCommand:command];
     }
}

- (void) logOut: (CDVInvokedUrlCommand *)command{
    [self.commandDelegate runInBackground:^{
        [Indigitall logOutWithSuccess:^(INDevice * _Nonnull device) {
            [self successWithDevice:device command:command];
        } onError:^(INError * _Nonnull error) {
            [self failedWithCommand:command];
        }];
    }];
}


- (void) successWithCommand: (CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) successWithString:(NSString *)resultString command:(CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:resultString];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) successWithBool:(BOOL)resultBool command:(CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:resultBool];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) successWithDevice: (INDevice *)device command: (CDVInvokedUrlCommand *)command{
    NSDictionary *data = [CDVIndigitallParse jsonFromDevice: device];
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:data];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) successWithTopic: (NSArray<INTopic *> *)topics command: (CDVInvokedUrlCommand *)command{
    NSArray<NSDictionary *>* data = [CDVIndigitallParse jsonArrayFromtopics: topics];
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:data];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) failedWithCommand: (CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) failedWithString: (NSString *)message command:(CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void) failedWithNSDictionary: (NSDictionary *)dic command:(CDVInvokedUrlCommand *)command{
    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dic];
    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

@end
