//
//  CDVInAppUtils.m
//  Indigitall
//
//  Created by indigitall on 13/12/23.
//

#import "CDVInAppUtils.h"

#import <Indigitall/INCoreUtils.h>
#import <Indigitall/INInAppDao.h>
#import <Indigitall/INInAppSchema.h>
#import <Indigitall/INEventUtils.h>
#import <Indigitall/INHmacUtils.h>
#import "CDVInAppHandler.h"

@implementation CDVInAppUtils
+ (void) inAppWasGot: (NSString *)inAppCode
            closePopupWhenClicked: (BOOL)closePopupWhenClicked
            didFound: (void(^)(INInApp *inApp))didFound
            notFound: (void(^)(void))notFound
             isPopUp: (BOOL) popUp
                view: (nullable UIView *)view
           closeIcon:(nullable UIButton *)closeIcon
   closeIconDisabled:(Boolean)closeIconDisabled
           didAppear:(nullable void(^)(void))didAppear
           didCancel:(nullable void(^)(void))didCancel
  didTouchWithAction:(nullable void(^)(INInAppAction *inAppAction))action
        didDismissed:(nullable void(^)(void))didDismissed
  onShowTimeFinished:(nullable void(^)(INInApp *inApp, int showTime))onShowTimeFinished
          didExpired:(nullable void(^)(INInApp *inApp, INError *error))didExpired
    didShowManyTimes:(nullable void(^)(INInApp *inApp, INError *error))didShowManyTimes
         didClickOut:(nullable void(^)(INInApp *inApp, INError *error))didClickOut
   didDismissForever:(nullable void(^)(INInApp *inApp, INError *error))didDismissForever
             success:(nullable void(^)(INInApp *))success
              failed:(nullable void(^)(INError *error))failed
          formFailed:(nullable void(^)(NSArray <INInAppError *>*error))formFailed
          formSubmit:(nullable void(^)(INInApp *inApp, NSDictionary *json))formSubmit
{
    INInApp *inApp = [INInAppDao searchInApp:inAppCode];
    [self inAppFilterControl:inApp closePopupWhenClicked: closePopupWhenClicked didFound:didFound notFound:notFound isPopUp:popUp view:view inAppCode:inApp.code closeIcon:closeIcon closeIconDisabled:closeIconDisabled didAppear:didAppear didCancel:didCancel didTouchWithAction:action didDismissed:didDismissed onShowTimeFinished:onShowTimeFinished didExpired:didExpired didShowManyTimes:didShowManyTimes didClickOut:didClickOut didDismissForever:didDismissForever success:success failed:failed formFailed:formFailed formSubmit:formSubmit];
    
}

+ (void) inAppFilterControl: (INInApp *)inApp
      closePopupWhenClicked: (BOOL)closePopupWhenClicked
                   didFound: (void(^)(INInApp *inApp))didFound
                   notFound: (void(^)(void))notFound
                    isPopUp: (BOOL) popUp
                       view: (UIView *)view
                  inAppCode: (NSString *)inAppCode
                  closeIcon:(nullable UIButton *)closeIcon
          closeIconDisabled:(Boolean)closeIconDisabled
                  didAppear:(nullable void(^)(void))didAppear
                  didCancel:(nullable void(^)(void))didCancel
         didTouchWithAction:(nullable void(^)(INInAppAction *inAppAction))action
               didDismissed:(nullable void(^)(void))didDismissed
         onShowTimeFinished:(nullable void(^)(INInApp *inApp, int showTime))onShowTimeFinished
                 didExpired:(nullable void(^)(INInApp *inApp, INError *error))didExpired
           didShowManyTimes:(nullable void(^)(INInApp *inApp, INError *error))didShowManyTimes
                didClickOut:(nullable void(^)(INInApp *inApp, INError *error))didClickOut
          didDismissForever:(nullable void(^)(INInApp *inApp, INError *error))didDismissForever
                    success:(nullable void(^)(INInApp *))success
                     failed:(nullable void(^)(INError *error))failed
                 formFailed:(nullable void(^)(NSArray <INInAppError *>*error))formFailed
                 formSubmit:(nullable void(^)(INInApp *inApp, NSDictionary *json))formSubmit
{
    NSDate *now = [INDateUtils getDateNow];
    if (inApp != nil) {
        NSDate *dateExpired = [INDateUtils getDate:inApp.expiredDate];
        if ([now compare:dateExpired] == NSOrderedAscending){
            INInAppError *error = [self wasInAppPassedFilterProperties:inApp];
            if (error != nil) {
                if (error.inAppErrorCode == INAPP_SHOW_POPUP_ERROR) {
                    if (didDismissForever != nil) didDismissForever(inApp, error);
                } else if (error.inAppErrorCode == INAPP_WAS_SHOWN_MANY_TIMES) {
                    if (didShowManyTimes != nil) didShowManyTimes(inApp, error);
                } else if (error.inAppErrorCode == INAPP_WAS_CLICKED_MANY_TIMES) {
                    if (didClickOut != nil) didClickOut(inApp, error);
                }
                return;
            }
            if (didFound != nil) didFound(inApp);
            return;
        } else {
            if (didExpired != nil) didExpired(inApp, [[INInAppError alloc]initWithErrorCode:INAPP_WAS_EXPIRED descriptionMessage:nil]);
            [self updateInAppGetWithInAppDb:inApp closePopupWhenClicked: closePopupWhenClicked isPopUp:popUp view:view inAppCode:inApp.code closeIcon:closeIcon closeIconDisabled:closeIconDisabled didAppear:didAppear didCancel:didCancel didTouchWithAction:action didDismissed:didDismissed onShowTimeFinished:onShowTimeFinished didExpired:didExpired didShowManyTimes:didShowManyTimes didClickOut:didClickOut didDismissForever:didDismissForever success:success failed:failed formFailed:formFailed formSubmit:formSubmit];
            return;
        }
    }
    if (notFound != nil) notFound();
}

+ (INInAppError *) wasInAppPassedFilterProperties: (INInApp *) inApp {
    if (inApp != nil) {
        if (inApp.properties.dismissForever &&
            inApp.inAppShow.wasDismissed == true) {
            return [[INInAppError alloc]initWithErrorCode:INAPP_SHOW_POPUP_ERROR descriptionMessage:nil];
        } else {
            int numberOfShows = inApp.properties.numberOfShows;
            int timesShowed = inApp.inAppShow.timesShowed;
            int numberOfClicks = inApp.properties.numberOfClicks;
            int timesClicked = inApp.inAppShow.timesClicked;
            if (numberOfShows > 0) {
                if (timesShowed < numberOfShows) {
                    NSNumber *result = [NSNumber numberWithInt:(timesShowed + 1)];
                    [INInAppDao updateInAppField:inApp key:INInAppSchema.COLUMN_INAPP_SHOW_TIMES_SHOWED value:result];
                } else {
                    return [[INInAppError alloc]initWithErrorCode:INAPP_WAS_SHOWN_MANY_TIMES descriptionMessage:[NSString stringWithFormat:@"Showed more than %d times", numberOfShows]];
                }
            }
            if (numberOfClicks > 0) {
                if (timesClicked >= numberOfClicks) {
                    return [[INInAppError alloc]initWithErrorCode:INAPP_WAS_CLICKED_MANY_TIMES descriptionMessage:[NSString stringWithFormat:@"Clicked more than %d times", numberOfClicks]];
                }
            }
        }
    }
    return nil;
}

+ (void) updateInAppGetWithInAppDb: (INInApp *)inAppDb
             closePopupWhenClicked: (BOOL)closePopupWhenClicked
                           isPopUp: (BOOL) popUp
                              view: (UIView *)view
                         inAppCode: (NSString *)inAppCode
                         closeIcon:(nullable UIButton *)closeIcon
                 closeIconDisabled:(Boolean)closeIconDisabled
                         didAppear:(nullable void(^)(void))didAppear
                         didCancel:(nullable void(^)(void))didCancel
                didTouchWithAction:(nullable void(^)(INInAppAction *inAppAction))action
                      didDismissed:(nullable void(^)(void))didDismissed
                onShowTimeFinished:(nullable void(^)(INInApp *inApp, int showTime))onShowTimeFinished
                        didExpired:(nullable void(^)(INInApp *inApp, INError *error))didExpired
                  didShowManyTimes:(nullable void(^)(INInApp *inApp, INError *error))didShowManyTimes
                       didClickOut:(nullable void(^)(INInApp *inApp, INError *error))didClickOut
                 didDismissForever:(nullable void(^)(INInApp *inApp, INError *error))didDismissForever
                           success:(nullable void(^)(INInApp *))success
                            failed:(nullable void(^)(INError *error))failed
                        formFailed:(nullable void(^)(NSArray <INInAppError *>*error))formFailed
                        formSubmit:(nullable void(^)(INInApp *inApp, NSDictionary *json))formSubmit
{
    [CDVInAppHandler getInAppToUpdate:inAppCode success:^(INInApp * _Nonnull inApp) {
        if ([INInAppDao updateInAppField:inApp withInAppDb:inAppDb keys:nil values:nil]){
            INInApp *newInApp = [INInAppDao searchInApp:inAppCode];
            INInAppError *error = [self wasInAppPassedFilterProperties:newInApp];
            if (error != nil) {
                if (error.inAppErrorCode == INAPP_SHOW_POPUP_ERROR) {
                    if (didDismissForever != nil) didDismissForever(newInApp, error);
                } else if (error.inAppErrorCode == INAPP_WAS_SHOWN_MANY_TIMES) {
                    if (didShowManyTimes != nil) didShowManyTimes(newInApp, error);
                } else if (error.inAppErrorCode == INAPP_WAS_CLICKED_MANY_TIMES) {
                    if (didClickOut != nil) didClickOut(newInApp, error);
                }
            } else {
                if (popUp) {
                    [[[CDVInAppHandler alloc]init] handlePopUp:newInApp popupCode:inAppCode closePopupWhenClicked:closePopupWhenClicked closeIcon:closeIcon closeIconDisabled:closeIconDisabled didAppear:didAppear didCancel:didCancel didTouchWithAction:action didDismissed:didDismissed onShowTimeFinished:onShowTimeFinished didExpired:didExpired didShowManyTimes:didShowManyTimes didClickOut:didClickOut didDismissForever:didDismissForever failed:failed formFailed:formFailed formSubmit:formSubmit];
                } else {
                    [[INInAppHandler alloc]handleInApp:newInApp inAppCode:inAppCode view:view didTouchWithAction:action onShowTimeFinished:onShowTimeFinished didExpired:didExpired didShowManyTimes:didShowManyTimes didClickOut:didClickOut success:success failed:failed formFailed:formFailed formSubmit:formSubmit];
                }
            }
        } else {
            if (failed != nil) failed([[INError alloc]initWithErrorCode:GENERAL_ERROR descriptionMessage:@"InApp was not updated after get from cache"]);
        }
        } errorLoad:failed];
}

+ (void) addNewInApp:(INInApp *)inApp {
    [INInAppDao addNewInApp:inApp];
}

+ (void) inAppWasTappedWithInApp:(INInApp *)inApp {
    if (![self isNoActionInApp: inApp.properties.action]){
        if (inApp != nil && inApp.properties.numberOfClicks > 0) [CDVInAppUtils addInAppNewClick:inApp];
        [INEventUtils eventClickInAppRequest:inApp];
    }
}

+ (void) addInAppNewClick:(INInApp *)inApp {
    NSNumber *result = [NSNumber numberWithInt:(inApp.inAppShow.timesClicked + 1)];
    [INInAppDao updateInAppField:inApp key:INInAppSchema.COLUMN_INAPP_SHOW_TIMES_CLICKED value:result];
}

+ (void) inAppOpenUrl: (INInAppAction *) action {
    if (![self isNoActionInApp: action]){
        NSURL *url;
        if (action.app != nil){
            url = [NSURL URLWithString:action.app];
        }else if(action.url != nil){
            url = [NSURL URLWithString:action.url];
        }
        [self openUrl:url];
    }
}

+ (NSDictionary *) convertToNSDictionary: (NSString *)jsonString{
    id hashMap = nil;
    if (jsonString != nil && ![jsonString isEqual:@""]){
        NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        hashMap = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    }
    return [hashMap copy];
}

+ (void) setHashMap: (NSDictionary *)newHashMap type: (int) type{
    NSError * err;
    NSData * jsonData = [NSJSONSerialization  dataWithJSONObject:newHashMap options:0 error:&err];
    NSString * myString = [[NSString alloc] initWithData:jsonData   encoding:NSUTF8StringEncoding];
    if (type == 0) {
        [INInAppDefaults setInAppShowOnce: myString];
    } else if (type == 1) {
        [INInAppDefaults setInAppTimesClicked: myString];
    } else if (type == 2) {
        [INInAppDefaults setInAppDismissForever:myString];
    } else if (type == 3) {
        [INInAppDefaults setInAppWasGot:myString];
    }
}

+ (void) openUrl: (NSURL *)url {
    if (url != nil) {
        if ([UIApplication.sharedApplication canOpenURL:url]){
            if (@available(iOS 10.0, *)) {
                [UIApplication.sharedApplication openURL:url options:[[NSDictionary alloc] init] completionHandler:nil];
            }else{
                [UIApplication.sharedApplication openURL:url];
            }
            return;
        }
    }
}

+ (BOOL) isNoActionInApp: (INInAppAction *) action {
    if (action.noAction == nil && ![action.noAction isEqualToString:INInAppAPIConstants.typeNoAction]){
        return false;
    }
    return true;
}

+ (BOOL) isInAppDismissForever: (INInApp *)inApp {
    INInApp *inAppDB = [INInAppDao searchInApp:inApp.code];
    if (inAppDB != nil &&
        inAppDB.properties.dismissForever) {
        return true;
    }
    return false;
}

+ (void) addNewInAppToDismissForever:(INInApp *)inApp {
    [INInAppDao updateInAppField:inApp key:INInAppSchema.COLUMN_WAS_DISMISSED value:[NSNumber numberWithBool:true]];
}

+ (NSString *) setExternalCode: (NSString *) code {
    NSString* externalCode = [[INHmacUtils alloc]hmacsha256:code secret:[INInAppDefaults getAppKey]];
    [INInAppDefaults setExternalId:externalCode];
    return externalCode;
}

+ (INInAppAction *) getInAppActionFromString: (NSString *)actionString{
    NSMutableDictionary *actionJSON = [[NSJSONSerialization JSONObjectWithData:[actionString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil] objectForKey:@"action"];
    return [[INInAppAction alloc] init:actionJSON];
    
}

@end
