#import "RCTIREventEmitter.h"
#import "RNInvitereferrals.h"
#import <UIKit/UIKit.h>

BOOL wasDelegateSet = NO;

@implementation RCTIREventEmitter{
    BOOL hasListeners;
}

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

static BOOL _startObserving = false;

+ (BOOL)hasSetBridge {
    return _startObserving;
}

+(BOOL)requiresMainQueueSetup {
    return YES;
}

RCT_EXPORT_MODULE(RNInvitereferrals);
//RCT_EXPORT_MODULE();

#pragma mark RCTEventEmitter Subclass Methods

-(instancetype)init {
    if (self = [super init]) {
        NSLog(@"init method was called");
        for (NSString *eventName in [self supportedEvents]) {
            [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(emitEvent:) name: eventName object: nil];
        }
    }
    return self;
}

- (NSArray<NSString *> *)supportedEvents {
    return @[@"ir_tracking_event", @"ir_campaign_callbacks"];
}

// Will be called when this module's first listener is added.
- (void)startObserving {
    hasListeners = YES;
    NSLog(@"startObserving method was called");
    [[NSNotificationCenter defaultCenter] postNotificationName:@"didSetBridge" object:nil];
    _startObserving = true;
}

// Will be called when this module's last listener is removed, or on dealloc.
- (void)stopObserving {
    NSLog(@"stopObserving method was called");
    hasListeners = NO;
}

// Send Event Methods
- (void)emitEvent:(NSNotification *)notification {
    if (!hasListeners) {
        NSLog(@"Attempted to send an event. When no listeners were set");
        return;
    }
    [self sendEventWithName:notification.name body:notification.userInfo];
}

+ (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body {
        NSLog(@"sendEventWithName method was called");
        [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:body];
}


#pragma mark - CAMPAIGN METHODS

/*Campaign Function */
RCT_EXPORT_METHOD(campaign:(NSDictionary *)campaignInfo userInfo:(NSDictionary *)userInfo ){
    @try {
        NSLog(@"campaign ios!!");
        [self setIRDelegate];
        IRCampaignInfo *irRNCampaignData = [self createIRCampaignInfoWithCampaignDataDict: campaignInfo];
        IRUserInfo *irRNUserData = [self createIRUserInfoWithUserDataDict: userInfo];
       
        [[InviteReferrals sharedInstance] campaign: irRNCampaignData userInfo: irRNUserData campaignCompletion:^(NSDictionary *irCampaignResponse) {
            if([irCampaignResponse count] > 0){
                NSMutableDictionary * temp = [irCampaignResponse mutableCopy];
                [temp setObject:@"campaignScreen" forKey:@"callback_type"];
                NSError *nvError = nil;
                NSData *nvJsonData = [NSJSONSerialization dataWithJSONObject: temp options: NSJSONWritingPrettyPrinted error: &nvError];
                NSString * irResponseStr = [[NSString alloc] initWithData: nvJsonData encoding: NSUTF8StringEncoding];
                [self sendEventWithName:@"ir_campaign_callbacks" body:@{@"data":irResponseStr}];
            } else {
                NSLog(@"No Data Found !!");
            }
        }];
        
    } @catch (NSException *exception) {
        NSLog(@"%@", exception.reason);
    }
    
}

/*Campaign Popup Function */
RCT_EXPORT_METHOD(campaignPopup:(NSString *)ruleName campaignInfo:(NSDictionary *)campaignInfo userInfo:(NSDictionary *)userInfo) {
    @try{
        NSLog(@"Campaign Popup !!");
        [self setIRDelegate];
        IRCampaignInfo *irRNCampaignData = [self createIRCampaignInfoWithCampaignDataDict: campaignInfo];
        IRUserInfo *irRNUserData = [self createIRUserInfoWithUserDataDict: userInfo];
        [[InviteReferrals sharedInstance] campaignPopupForRuleName: ruleName campaignInfo: irRNCampaignData userInfo: irRNUserData];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

//GET SHARING DETAILS
RCT_EXPORT_METHOD(getSharingDetails:(NSDictionary *)campaignInfo userInfo:(NSDictionary *)userInfo sharingData:(RCTResponseSenderBlock)callback) {
    @try {
        NSLog(@"GET SHARING DETAILS !!");
        IRCampaignInfo *irRNCampaignData = [self createIRCampaignInfoWithCampaignDataDict: campaignInfo];
        IRUserInfo *irRNUserData = [self createIRUserInfoWithUserDataDict: userInfo];
        
[[InviteReferrals sharedInstance] getSharingDetailsWithCampaignInfo: irRNCampaignData userInfo: irRNUserData sharingData:^(NSDictionary *irSharingData) {
    if([irSharingData count] > 0){
        NSError *nvError = nil;
NSData *nvJsonData = [NSJSONSerialization dataWithJSONObject: irSharingData options: NSJSONWritingPrettyPrinted error: &nvError];
NSString *nvJsonString = [[NSString alloc] initWithData: nvJsonData encoding: NSUTF8StringEncoding];
        callback(@[nvJsonString, [NSNull null]]);
    }else{
        callback(@[@"No Data Found !! ", [NSNull null]]);
    }
}];
    } @catch (NSException *exception) {
        callback(@[exception.reason, [NSNull null]]);
        NSLog(@"%@", exception.reason);
    }
}

#pragma mark - TRACKING EVENTS METHOD
/* tracking events */
RCT_EXPORT_METHOD(tracking:(NSDictionary *)eventInfo userInfo:(NSDictionary *)userInfo withTrackingCompletionResponse:(RCTResponseSenderBlock) callback) {
    @try {
        NSLog(@"InviteReferrals-RN Tracking !!");
        self.trackingResult = callback;
        [self setIRDelegate];
        IREventInfo *irRNEventData = [self createIREventInfoWithEventDataDict: eventInfo];
        IRUserInfo *irRNUserData = [self createIRUserInfoWithUserDataDict: userInfo];
        [[InviteReferrals sharedInstance] trackingforEventInfo: irRNEventData userInfo: irRNUserData];
    } @catch (NSException *exception) {
        NSLog(@"%@", exception.reason);
    }
}

#pragma mark - OTHER USEFUL METHODS

/* for first time to show welcome message */
RCT_EXPORT_METHOD(showWelcomeMessage){
    @try{
        NSLog(@"SHOW WELCOME MESSAGE !!");
        [[InviteReferrals sharedInstance] showWelcomeMessage];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* for getting referrer code */
RCT_EXPORT_METHOD(getReferrerCode:(RCTResponseSenderBlock)callback){
    @try{
        NSLog(@"GET REFERRER CODE !!");
[[InviteReferrals sharedInstance] getReferrerCode:^(NSString *irRefCode) {
            if([irRefCode length] > 0 ){
                callback(@[irRefCode, [NSNull null]]);
            }else{
                callback(@[@"null", [NSNull null]]);
            }
        }];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* Refererr Parameters */
RCT_EXPORT_METHOD(getReferringParams:(RCTResponseSenderBlock)callback){
    @try{
        NSLog(@"GET REFERRING PARAMS !!");
        
[[InviteReferrals sharedInstance] getReferringParams:^(NSDictionary *irRefParams) {
    if([irRefParams count] > 0 ){
        NSError * irErr;
        NSData * irResponseJsonData = [NSJSONSerialization dataWithJSONObject: irRefParams options: 0 error: &irErr];
        NSString * irResponseStr = [[NSString alloc] initWithData: irResponseJsonData encoding: NSUTF8StringEncoding];
        callback(@[irResponseStr, [NSNull null]]);
            } else{
                callback(@[@"null", [NSNull null]]);
            }
        }];
        
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* set language */
RCT_EXPORT_METHOD(setLocale:(NSString *)irLanguageCode){
    @try{
        NSLog(@"SET LOCALE !!");
        [[InviteReferrals sharedInstance] setLocalizationLanguage: irLanguageCode];
    } @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* Track Invite */
RCT_EXPORT_METHOD(trackInvite:(NSString *)inviteParameter campaignID:(NSString *)campaignID) {
    @try{
        NSString *irTemCampaignID = [NSString stringWithFormat: @"%@", campaignID];
        NSInteger invrFinalCampaignID = 0;
        if ([irTemCampaignID length] > 0 && ![irTemCampaignID isEqualToString: @""] && ![irTemCampaignID isEqual: [NSNull null]]) {
            invrFinalCampaignID = [irTemCampaignID integerValue];
        }
        NSString *invrInviteSourceName = [NSString stringWithFormat: @"%@", inviteParameter];
        
        [[InviteReferrals sharedInstance] trackInviteWithSourceName: invrInviteSourceName campaignID: invrFinalCampaignID];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* Logout from IRCampaign*/
RCT_EXPORT_METHOD(logout) {
    @try{
        NSLog(@"Logout from IRCampaign!!");
        [[InviteReferrals sharedInstance] logout];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

#pragma mark - InviteReferralsDelegate Listener Methods

/* set Inviteferrals Delegate */
-(void)setIRDelegate{
    @try {
        NSLog(@"SET IR DELEGATE!!");
        if(!wasDelegateSet){
            [InviteReferrals sharedInstance].delegate = self;
            wasDelegateSet = YES;
        } else{
            NSLog(@"IR DELEGATE ALLREADY SET !!");
        }
    }@catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
    
}

/* Close Button callback event */
RCT_EXPORT_METHOD(closeButtonListener){
    @try{
        NSLog(@"CLOSE BUTTON LISTENER !!");
        [self setIRDelegate];
    }
    @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* tracking callback event */
-(void)InviteReferralsTrackingFinishedforEventInfo:(NSDictionary *)trackingResponse {
    dispatch_async(dispatch_get_main_queue(), ^{

        if (!self.bridge) {
            self.trackingResult = nil;
            return;
        }

        if (!self.trackingResult) {
            return;
        }

        @try {

            NSString *responseString = @"Tracking Data Unavailable !!";

            if (trackingResponse.count > 0) {
                NSError *error = nil;
                NSData *jsonData = [NSJSONSerialization dataWithJSONObject: trackingResponse options: 0 error: &error];

                if (!error && jsonData) {
                    responseString = [[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding];
                }
            }

            self.trackingResult(@[responseString, [NSNull null]]);

        } @catch (NSException *exception) {
            NSLog(@"%@", exception.reason);
        }

        // 🔥 Prevent stale callback crash in Release
        self.trackingResult = nil;
    });
}

-(void)InviteReferralsOnSharingIconClickCallback:(NSDictionary *)sharingIconClickInfo {
    @try {
        NSLog(@"INVITEREFERRS ON SHARING ICON CLICK !!");
        
        NSMutableDictionary * temp = [sharingIconClickInfo mutableCopy];
        [temp setObject:@"shareIconClick" forKey:@"callback_type"];
        
        NSError * irErr;
        NSData * irResponseJsonData = [NSJSONSerialization dataWithJSONObject: temp options: 0 error: &irErr];
        NSString * irResponseStr = [[NSString alloc] initWithData: irResponseJsonData encoding: NSUTF8StringEncoding];
        [self sendEventWithName:@"ir_campaign_callbacks" body:@{@"data":irResponseStr}];
        
    }@catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

-(void)InviteReferralsLeadSentResponseCallback:(NSDictionary *)sentLeadResponse {
    @try {
        NSLog(@"INVITEREFERRS LEAD SENT RESPONSE !!");
        
        NSMutableDictionary * temp = [sentLeadResponse mutableCopy];
        [temp setObject:@"captureLeadForm" forKey:@"callback_type"];
        NSError * irErr;
        NSData * irResponseJsonData = [NSJSONSerialization dataWithJSONObject: temp options: 0 error: &irErr];
        NSString * irResponseStr = [[NSString alloc] initWithData: irResponseJsonData encoding: NSUTF8StringEncoding];
        [self sendEventWithName:@"ir_campaign_callbacks" body:@{@"data":irResponseStr}];
    }@catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

/* Close Button callback event */
-(void)InviteReferralsOnDoneButtonActionWithUserInfo:(NSDictionary *)userInfo {
    @try {
        NSLog(@"INVITEREFERRS ON DONE BUTTON ACTION  !!");
        
        NSMutableDictionary * temp = [userInfo mutableCopy];
        [temp setObject:@"closeButtonClick" forKey:@"callback_type"];
        NSError * irErr;
        NSData * irResponseJsonData = [NSJSONSerialization dataWithJSONObject: temp options: 0 error: &irErr];
        NSString * irResponseStr = [[NSString alloc] initWithData: irResponseJsonData encoding: NSUTF8StringEncoding];
        [self sendEventWithName:@"ir_campaign_callbacks" body:@{@"data":irResponseStr}];
        
    } @catch(NSException *exception){
        NSLog(@"%@", exception.reason);
    }
}

-(IRCampaignInfo *)createIRCampaignInfoWithCampaignDataDict:(NSDictionary *)campaignDataDict {
    @try {
    IRCampaignInfo *irRNFinalCampaignInfo = [[IRCampaignInfo alloc] init];
        if([campaignDataDict count] > 0) {
            NSString *irRNCampaignIDStr = nil;
            NSInteger irRNCampaignIDInt = 0;
            NSString *irRNTemplateIDStr = nil;
            NSInteger irRNTemplateIDInt = 0;
            if(campaignDataDict[@"campaignID"]) {
                irRNCampaignIDStr = [NSString stringWithFormat: @"%@", campaignDataDict[@"campaignID"]];
            }
            if([irRNCampaignIDStr length] > 0 && ![irRNCampaignIDStr isEqualToString: @""] && ![irRNCampaignIDStr isEqual: [NSNull null]]) {
                irRNCampaignIDInt = [irRNCampaignIDStr integerValue];
            }
            
            if(campaignDataDict[@"templateID"]) {
                irRNTemplateIDStr = [NSString stringWithFormat: @"%@", campaignDataDict[@"templateID"]];
            }
            
            if([irRNTemplateIDStr length] > 0 && ![irRNTemplateIDStr isEqualToString: @""] && ![irRNTemplateIDStr isEqual: [NSNull null]]) {
                irRNTemplateIDInt = [irRNTemplateIDStr integerValue];
            }
            
            irRNFinalCampaignInfo.campaignID = irRNCampaignIDInt;
            irRNFinalCampaignInfo.templateID = irRNTemplateIDInt;
            
        }
        return  irRNFinalCampaignInfo;
    } @catch (NSException *exception) {
        return  [[IRCampaignInfo alloc] init];
    }
}

-(IRUserInfo *)createIRUserInfoWithUserDataDict:(NSDictionary *)userDataDict {
    @try {
        IRUserInfo *irRNFinalUserInfo = [[IRUserInfo alloc] init];
        if([userDataDict count] > 0) {
            NSString *irRNCustomValueOne = nil;
            NSString *irRNCustomValueTwo = nil;
            NSString *irRNUserEmail = nil;
            NSString *irRNUserMobileNo = nil;
            NSString *irRNUserFullName = nil;
            NSString *irRNSubscriptionID = nil;
            
            if(userDataDict[@"customValueOne"]) {
                irRNCustomValueOne = [NSString stringWithFormat: @"%@", userDataDict[@"customValueOne"]];
            }
            
            if([irRNCustomValueOne length] > 0 && ![irRNCustomValueOne isEqualToString: @""] && ![irRNCustomValueOne isEqual: [NSNull null]]) {
                irRNFinalUserInfo.customValueOne = irRNCustomValueOne;
            }
            
            if(userDataDict[@"customValueTwo"]) {
                irRNCustomValueTwo = [NSString stringWithFormat: @"%@", userDataDict[@"customValueTwo"]];
            }
            
            if([irRNCustomValueTwo length] > 0 && ![irRNCustomValueTwo isEqualToString: @""] && ![irRNCustomValueTwo isEqual: [NSNull null]]) {
                irRNFinalUserInfo.customValueTwo = irRNCustomValueTwo;
            }
            
            if(userDataDict[@"email"]) {
                irRNUserEmail = [NSString stringWithFormat: @"%@", userDataDict[@"email"]];
            }
            
            if([irRNUserEmail length] > 0 && ![irRNUserEmail isEqualToString: @""] && ![irRNUserEmail isEqual: [NSNull null]]) {
                irRNFinalUserInfo.email = irRNUserEmail;
            }
            
            if(userDataDict[@"mobileNo"]) {
                irRNUserMobileNo = [NSString stringWithFormat: @"%@", userDataDict[@"mobileNo"]];
            }
            
            if([irRNUserMobileNo length] > 0 && ![irRNUserMobileNo isEqualToString: @""] && ![irRNUserMobileNo isEqual: [NSNull null]]) {
                irRNFinalUserInfo.mobileNo = irRNUserMobileNo;
            }
            
            if(userDataDict[@"name"]) {
                irRNUserFullName = [NSString stringWithFormat: @"%@", userDataDict[@"name"]];
            }
            
            if([irRNUserFullName length] > 0 && ![irRNUserFullName isEqualToString: @""] && ![irRNUserFullName isEqual: [NSNull null]]) {
                irRNFinalUserInfo.name = irRNUserFullName;
            }
            
            if(userDataDict[@"subscriptionID"]) {
                irRNSubscriptionID = [NSString stringWithFormat: @"%@", userDataDict[@"subscriptionID"]];
            }
            
            if([irRNSubscriptionID length] > 0 && ![irRNSubscriptionID isEqualToString: @""] && ![irRNSubscriptionID isEqual: [NSNull null]]) {
                irRNFinalUserInfo.subscriptionID = irRNSubscriptionID;
            }
            
        }
        return irRNFinalUserInfo;
    } @catch (NSException *exception) {
        return  [[IRUserInfo alloc] init];
    }
}


-(IREventInfo *)createIREventInfoWithEventDataDict:(NSDictionary *)eventDataDict {
    @try {
        IREventInfo *irRNFinalEventInfo = [[IREventInfo alloc] init];
        if([eventDataDict count] > 0) {
        
            NSString *irRNEventName = nil;
            NSString *irRNOrderID = nil;
            NSString *irRNPurchaseValueStr = nil;
            double irRNPurchaseValueDbl = 0;
            NSString *irRNReferrerCode = nil;
            NSString *irRNUniqueCode = nil;
            NSString *irRNOrderCustomValue = nil;
            
            if(eventDataDict[@"eventName"]) {
                irRNEventName = [NSString stringWithFormat: @"%@", eventDataDict[@"eventName"]];
            }
            
            if([irRNEventName length] > 0 && ![irRNEventName isEqualToString: @""] && ![irRNEventName isEqual: [NSNull null]]) {
                irRNFinalEventInfo.eventName = irRNEventName;
            }
            
            if(eventDataDict[@"orderID"]) {
                irRNOrderID = [NSString stringWithFormat: @"%@", eventDataDict[@"orderID"]];
            }
            
            if([irRNOrderID length] > 0 && ![irRNOrderID isEqualToString: @""] && ![irRNOrderID isEqual: [NSNull null]]) {
                irRNFinalEventInfo.orderID = irRNOrderID;
            }
            
            if(eventDataDict[@"purchaseValue"]) {
                irRNPurchaseValueStr = [NSString stringWithFormat: @"%@", eventDataDict[@"purchaseValue"]];
            }
            
            if([irRNPurchaseValueStr length] > 0 && ![irRNPurchaseValueStr isEqualToString: @""] && ![irRNPurchaseValueStr isEqual: [NSNull null]]) {
                irRNPurchaseValueDbl = [irRNPurchaseValueStr doubleValue];
            }
            
            irRNFinalEventInfo.purchaseValue = irRNPurchaseValueDbl;
            
            if(eventDataDict[@"referrerCode"]) {
                irRNReferrerCode = [NSString stringWithFormat: @"%@", eventDataDict[@"referrerCode"]];
            }
            
if([irRNReferrerCode length] > 0 && ![irRNReferrerCode isEqualToString: @""] && ![irRNReferrerCode isEqual: [NSNull null]]) {
                irRNFinalEventInfo.referrerCode = irRNReferrerCode;
            }
            
            if(eventDataDict[@"uniqueCode"]) {
                irRNUniqueCode = [NSString stringWithFormat: @"%@", eventDataDict[@"uniqueCode"]];
            }
            
            if([irRNUniqueCode length] > 0 && ![irRNUniqueCode isEqualToString: @""] && ![irRNUniqueCode isEqual: [NSNull null]]) {
                irRNFinalEventInfo.uniqueCode = irRNUniqueCode;
            }
            
            if(eventDataDict[@"orderCustomValue"]) {
                irRNOrderCustomValue = [NSString stringWithFormat: @"%@", eventDataDict[@"orderCustomValue"]];
            }
            
            if([irRNOrderCustomValue length] > 0 && ![irRNOrderCustomValue isEqualToString: @""] && ![irRNOrderCustomValue isEqual: [NSNull null]]) {
                irRNFinalEventInfo.orderCustomValue = irRNOrderCustomValue;
            }
        }
        return irRNFinalEventInfo;
    } @catch (NSException *exception) {
        return  [[IREventInfo alloc] init];
    }
}

@end
