
#import "appdooPublisherPNS.h"
#import "appdooPublisherSettings.h"
#import "NSURL+CreateWithParameters.h"
#import "HardwareInfo.h"
#import "SceneInputDataSource.h"
#import "appdooPublisherDataSource.h"

#define appdooPublisherURLPrefix								@"https://www.appdoo.info/publisher/"
#define appdooPublisherURLRegisterToken							@"" appdooPublisherURLPrefix "api/1/registertoken"
#define appdooPublisherURLResource								@"" appdooPublisherURLPrefix "api/1/resource"
#define appdooPublisherUserDefaultsRegisteredDeviceTokenKey		@"appdooPublisherRegisteredDeviceToken"
#define appdooPublisherNotificationMessageKey					@"CPMessage"
#define appdooPublisherNotificationResourceKey					@"CPResource"
#define appdooPublisherNotificationResourceGroupKey				@"CPResourceGroup"

typedef enum : NSUInteger {
    appdooPublisherActionNone = 0,
    appdooPublisherActionAlert = 1,
    appdooPublisherActionShowScene = 2
} appdooPublisherAction;


@interface appdooPublisherPNS ()

@property (strong, nonatomic) UIViewController * modalPNSViewController;

@end

@implementation appdooPublisherPNS {
	NSDictionary * _notification;
}

+ (instancetype)sharedInstance {

    static dispatch_once_t pred;
    static appdooPublisherPNS * sharedInstance;
    
	dispatch_once(&pred, ^{
        sharedInstance = [[self alloc] init];
    });
	
    return sharedInstance;
}

- (NSURL *)URLToRegisterToken:(NSData *)deviceToken {
	
	NSString * tokenString = [NSString stringWithFormat:@"%@", deviceToken];
	NSString * appBundleID = [[NSBundle mainBundle] bundleIdentifier];
	NSString * deviceVendorID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

	NSString * inDevelopment =
#ifdef DEBUG
	@"1";
#else
	@"0";
#endif
	
	NSMutableDictionary * parameters = @{
		@"developerID": [[appdooPublisherSettings sharedSettings] developerID],
		@"token": tokenString,
		@"development": inDevelopment,
		@"appBundleID": appBundleID,
		@"deviceVendorID": deviceVendorID,
		@"appBundleVersion": [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]
	}.mutableCopy;
	
	// With Device Info:
	if ([[appdooPublisherSettings sharedSettings] deviceStatisticsEnabled]) {
		
		[parameters setObject:[[UIDevice currentDevice] systemVersion] forKey:@"systemVersion"];
		[parameters setObject:[HardwareInfo hardwareString] forKey:@"deviceType"];

	}

	return [NSURL URLWithString:appdooPublisherURLRegisterToken
			  parameters:parameters];
}

+ (void)applicationDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#if TARGET_IPHONE_SIMULATOR
	// Remote notifications are only available on physical devices.
#else
	
	if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
	{
#ifdef __IPHONE_8_0
		[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
		[[UIApplication sharedApplication] registerForRemoteNotifications];
#else
#pragma message "You must use Xcode 6 or later to register for push notifications in iOS 8."
#endif
	}
	else
	{
#ifdef __IPHONE_8_0
		UIRemoteNotificationType types = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
#else
		UIRemoteNotificationType types = (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound);
#endif
		[[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
	}

	
	NSDictionary * notification = [launchOptions valueForKeyPath:UIApplicationLaunchOptionsRemoteNotificationKey];
	if (notification) {
		// It the app is launching, wait a second.
		dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
			[self handlePush:notification wasInactive:YES];
		});
		
	}
#endif
}

+ (void)applicationDidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

	NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
	
	//if ([[userDefaults dataForKey:appdooPublisherUserDefaultsRegisteredDeviceTokenKey] isEqualToData:deviceToken]) return;

	NSURL * url = [self.sharedInstance URLToRegisterToken:deviceToken];
	
	[[[NSURLSession sharedSession] dataTaskWithURL:url
								 completionHandler:^(NSData *data,
													 NSURLResponse *response,
													 NSError *error) {
									 if (error) {
										 NSLog(@"Connection error when trying to send device token: %@", error);
										 return;
									 }
									 
									 if ([data isEqualToData:[@"OK" dataUsingEncoding:NSUTF8StringEncoding]]) {
										 [userDefaults setObject:deviceToken forKey:appdooPublisherUserDefaultsRegisteredDeviceTokenKey];
									 }
									 else {
										 NSLog(@"Bad server response when trying to register the device for push notifications: %@", [NSString.alloc initWithData:data encoding:NSUTF8StringEncoding]);
									 }
								 }] resume];
}

- (NSURL *)URLForItemID:(NSString *)itemID {
	
	return [NSURL URLWithString:[appdooPublisherURLResource stringByAppendingPathComponent:itemID]];

}

+ (void)handlePush:(NSDictionary *)notificationInfo {

	if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
		[self handlePush:notificationInfo wasInactive:NO];
    }
	else {
		[self handlePush:notificationInfo wasInactive:YES];
	}
	
}

- (BOOL)shouldHandleNotification:(NSDictionary *)notification {
	return YES;
}

+ (void)handlePush:(NSDictionary *)notification wasInactive:(BOOL)isLaunching {

#ifdef DEBUG
	NSLog(@"App Received a Push Notification: %@", notification);
#endif
	
	if (![[self sharedInstance] shouldHandleNotification:notification])
		return;

	[self setAppIconBadge:0];

	NSString * resourceGroupID = [notification valueForKey:appdooPublisherNotificationResourceGroupKey];
	
	if (resourceGroupID.length) {
		[appdooPublisherDataSource updateInstancesWithResourceGroupID:resourceGroupID];
		[[self sharedInstance] triggerActionForNotification:notification isLaunching:isLaunching];
	}
	else {
		if (!isLaunching) {
			[[self sharedInstance] showAlertForNotification:notification];
		}
	}
		
}

- (void)showAlertForNotification:(NSDictionary *)notification {
	NSString * title = [notification valueForKeyPath:@"aps.alert"];
	NSString * message = [notification valueForKey:appdooPublisherNotificationMessageKey];
	
	//[[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"Close", nil) otherButtonTitles:NSLocalizedString(@"OK", nil), nil] show];
	
	UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
	[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", nil) style:UIAlertActionStyleDefault handler:nil]];
	[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:nil]];
	[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertController animated:YES completion:nil];
}

- (void)triggerActionForNotification:(NSDictionary *)notification isLaunching:(BOOL)isLaunching {

	NSString * datasetResourceID = [notification valueForKey:appdooPublisherNotificationResourceKey];
	NSString * datasetGroupResourceID = [notification valueForKey:appdooPublisherNotificationResourceGroupKey];
	
	appdooPublisherSettings * settings = appdooPublisherSettings.sharedSettings;

	NSDictionary * apnHandlerInfo = [settings.pushNotificationEventHandlers valueForKey:datasetGroupResourceID];
	
	if (apnHandlerInfo) {
		NSString * apnHandlerType = apnHandlerInfo[@"type"];

		if ([apnHandlerType isEqualToString:@"scene"]) {
			
			if (isLaunching) {
			
				NSString * sceneID = [apnHandlerInfo valueForKey:@"sceneID"];
				[self presentItemWithID:datasetResourceID inSceneWithID:sceneID];
				
			} else {
				
				NSString * title = [notification valueForKeyPath:@"aps.alert"];
				NSString * message = [notification valueForKey:appdooPublisherNotificationMessageKey];
				
				UIAlertController *controller = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
				[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"Cancel", @"appdooPublisherLocalized", 0) style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
					_notification = nil;
				}]];
				[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"Show", @"appdooPublisherLocalized", 0) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
					NSString * datasetGroupResourceID = [_notification valueForKey:appdooPublisherNotificationResourceGroupKey];
					NSString * datasetResourceID = [_notification valueForKey:appdooPublisherNotificationResourceKey];
					appdooPublisherSettings * settings = appdooPublisherSettings.sharedSettings;
					NSDictionary * apnHandlerInfo = [settings.pushNotificationEventHandlers valueForKey:datasetGroupResourceID];
					NSString * sceneID = [apnHandlerInfo valueForKey:@"sceneID"];
					[self presentItemWithID:datasetResourceID inSceneWithID:sceneID];
					_notification = nil;
				}]];
				_notification = notification;
				[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:controller animated:YES completion:nil];
				
			}
		}
	}
}

- (void)closeModalPNSViewController:(id)sender {

	[self.modalPNSViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
	self.modalPNSViewController = nil;
}

+ (void)setAppIconBadge:(NSInteger)count {
	[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}

- (UIViewController *)loadSceneWithID:(NSString *)sceneID {
	return [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:sceneID];
}

- (void)presentItemWithID:(NSString *)itemID inSceneWithID:(NSString *)sceneID {
	
	NSURL * itemURL = [self URLForItemID:itemID];
	
	[[[NSURLSession sharedSession] dataTaskWithURL:itemURL
								 completionHandler:^(NSData *data,
													 NSURLResponse *response,
													 NSError *error) {
									 if (error) return;
									 
									 NSError * parsingError = nil;
									 NSDictionary * item = [NSJSONSerialization JSONObjectWithData:data
																						   options:0 error:&parsingError];
									 
									 if (parsingError) return;
									 
									 if (![item isKindOfClass:[NSDictionary class]]) return;
									 
									 UIViewController * viewController = self.modalPNSViewController;
									 if (!viewController) viewController = [self loadSceneWithID:sceneID];
									 if (!viewController) return;
									 
									 UINavigationController * navigationController;
									 
									 if ([viewController isKindOfClass:[UINavigationController class]])
										 navigationController = (UINavigationController *)viewController;
									 else
										 navigationController = [UINavigationController.alloc initWithRootViewController:viewController];
									 
									 if ([navigationController.topViewController respondsToSelector:@selector(sceneInputDataSource)]) {
										 SceneInputDataSource * inputDataSource = [navigationController.topViewController valueForKey:@"sceneInputDataSource"];
										 [inputDataSource setContents:item indexPath:nil originalDataSource:nil];
										 [inputDataSource notifyObservers];
									 }
									 
									 if (navigationController.presentingViewController) return;
									 
									 if (!navigationController.topViewController.navigationItem.leftBarButtonItem) {
										 UIBarButtonItem * doneBarButtonItem = [UIBarButtonItem.alloc initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeModalPNSViewController:)];
										 navigationController.topViewController.navigationItem.leftBarButtonItem = doneBarButtonItem;
										 self.modalPNSViewController = viewController;
									 }
									 
									 
									 UIViewController * rootViewController = [UIApplication.sharedApplication keyWindow].rootViewController;
									 
									 if (!rootViewController.presentedViewController) {
										 [rootViewController presentViewController:navigationController animated:YES completion:^{}];
									 }
									 else {
										 [rootViewController dismissViewControllerAnimated:YES completion:^{
											 [rootViewController presentViewController:navigationController animated:YES completion:^{}];
										 }];
									 }
								 }] resume];
}

@end
