#import "SmartechPushReactNative.h"

#import <React/RCTLog.h>
#import <React/RCTConvert.h>
#import <React/RCTBundleURLProvider.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <NativeSmartechPushReactNativeSpec/NativeSmartechPushReactNativeSpec.h>
#endif

#import <SmartPush/SmartPush.h>

@implementation SmartechPushReactNative
RCT_EXPORT_MODULE()



- (NSArray<NSString *> *)supportedEvents {
    return @[kSMTNotificationReceiveIdentifier];
}

// REQUIRED: Override to prevent "Sending event without listeners" warnings
- (void)startObserving {
    // Set up any upstream listeners or background tasks here
    // This is called when JS side starts listening
     [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(emitEventInternal:)
                                                 name:kSMTNotificationReceiveIdentifier
                                               object:nil];

}

- (void)stopObserving {
    // Remove upstream listeners, stop background tasks
    // This is called when JS side stops listening
     [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)emitEventInternal:(NSNotification *)notification {
    [self sendEventWithName: notification.name body:notification.userInfo];
}
/**
 @brief This method is used to opt push notifications.
 
 @discussion If you call this method then we will opt in or opt out the user of recieving push notifications.
 */
RCT_EXPORT_METHOD(optPushNotification:(BOOL)isOpted) {
    RCTLogInfo(@"[Smartech optPushNotification]");
    @try {
        [[SmartPush sharedInstance] optPushNotification:isOpted];
    } @catch (NSException *exception) {
        NSLog(@"Smartech error: Exception caught in optPushNotification %@", exception.reason);
    }
}

/**
 @brief This method is used to get the current status of opt push notification.
 
 @discussion If you call this method you will get the current status of the tracking which can be used to render the UI at app level.
 */
RCT_EXPORT_METHOD(hasOptedPushNotification:(RCTResponseSenderBlock)callback) {
    RCTLogInfo(@"[Smartech hasOptedPushNotification]");
    @try {
        BOOL hasOpted = [[SmartPush sharedInstance] hasOptedPushNotification];
        [self returnResult:@(hasOpted) withCallback:callback andError:nil];
    } @catch (NSException *exception) {
        NSLog(@"Smartech error: Exception caught in hasOptedPushNotification %@", exception.reason);
    }
}

RCT_EXPORT_METHOD(postNotification:(NSString *)name) {
  [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:nil];
}

RCT_EXPORT_METHOD(registerForPushNotificationWithAuthorizationOptions:(BOOL)alert withBadge:(BOOL)badge andSound:(BOOL)sound) {
    UNAuthorizationOptions options = UNAuthorizationOptionNone;
    if (alert) {
        options += UNAuthorizationOptionAlert;
    }
    if (badge) {
        options += UNAuthorizationOptionBadge;
    }
    if (sound) {
        options += UNAuthorizationOptionSound;
    }
    [[SmartPush sharedInstance] registerForPushNotificationWithAuthorizationOptions:options];
}

/**
 @brief This method is used in the Android SDK to get device push token. In iOS it will be an empty implementation.
 */
RCT_EXPORT_METHOD(getDevicePushToken:(RCTResponseSenderBlock)callback) {
    RCTLogInfo(@"[SmartechPush getDevicePushToken is only implemented for Android.]");
    [self returnResult:@"" withCallback:callback andError:nil];
}

/**
 @brief This method is used in the Android SDK to set the device push token. In iOS it will be an empty implementation.
 */
RCT_EXPORT_METHOD(setDevicePushToken:(NSString *)token) {
    RCTLogInfo(@"[SmartechPush setDevicePushToken is only implemented for Android.]");
}

/**
 @brief This method is used in the Android SDK to set notification permission. In iOS it will be an empty implementation.
 */
RCT_EXPORT_METHOD(requestNotificationPermission:(RCTResponseSenderBlock)callback) {
    RCTLogInfo(@"[SmartechPush requestNotificationPermission is only implemented for Android.]");
    [self returnResult:@"" withCallback:callback andError:nil];
}

/**
 @brief This method is used in the Android SDK to uddate notification permission. In iOS it will be an empty implementation.
 */
RCT_EXPORT_METHOD(updateNotificationPermission:(int)pnPermissionStatus) {
    RCTLogInfo(@"[SmartechPush updateNotificationPermission is only implemented for Android.]");
}

/**
 @brief This method is used in the Android SDK to handle push notification payload provided by app. In iOS it will be an empty implementation.
 */
RCT_EXPORT_METHOD(handlePushNotification:(NSString *)notificationData callback:(RCTResponseSenderBlock)callback) {
  RCTLogInfo(@"[SmartechPush handlePushNotification is only implemented for Android.]");
  [self returnResult:@"" withCallback:callback andError:nil];
}


// #pragma mark - Helpers Methods

- (void)returnResult:(id)result withCallback:(RCTResponseSenderBlock)callback andError:(NSString *)error {
    if (callback == nil) {
        RCTLogInfo(@"Smartech callback was nil");
        return;
    }
    id errorValue = error != nil ? error : [NSNull null];
    id resultValue = result != nil ? result : [NSNull null];
    callback(@[errorValue, resultValue]);
}

+ (BOOL)requiresMainQueueSetup {
    return NO;
}

- (NSDictionary *)constantsToExport {
    return @{
        kSMTNotificationReceiveIdentifier : kSMTNotificationReceiveIdentifier
    };
}

- (NSDictionary *)getConstants {
    return @{
        kSMTNotificationReceiveIdentifier : kSMTNotificationReceiveIdentifier
    };
}

# pragma mark - Turbo Module

#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
  return std::make_shared<facebook::react::NativeSmartechPushReactNativeSpecJSI>(params);
}
#endif  

@end
