//
// UserNotificationsManager.m
// MapApp
//
// Created by Ziv on 16/12/17.
// Copyright © 2016年 Ziv. All rights reserved.
//

#import "UserNotificationsManager.h"
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import "Lang.h"
#import "AppLocalConfig.h"

@implementation NMNotificationContent
@end

@implementation NMNotificationTrigger
@end

@implementation NMNotificationRequest

- (UNNotificationRequest *)_transformToUNNotificationRequest {
	UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
	content.title = self.content.title;
	content.body = self.content.body;
	content.badge = @(self.content.badgeNumber);
	content.sound = self.content.soundName ? [UNNotificationSound soundNamed:self.content.soundName] : [UNNotificationSound defaultSound];
	content.userInfo = self.content.userInfo;
	UNNotificationTrigger *trigger = nil;
	if (self.trigger.region) {
		trigger = [UNLocationNotificationTrigger triggerWithRegion:self.trigger.region repeats:self.trigger.repeats];
	} else if (self.trigger.dateComponents) {
		trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:self.trigger.dateComponents repeats:self.trigger.repeats];
	} else if (self.trigger.timeInterval > 0) {
		trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:self.trigger.timeInterval repeats:self.trigger.repeats];
	}
	return [UNNotificationRequest requestWithIdentifier:self.identifier content:content trigger:trigger];
}

- (UILocalNotification *)_transformToUILocalNotification {
	UILocalNotification *localNotefication = [[UILocalNotification alloc] init];
	localNotefication.alertTitle = self.content.title;
	localNotefication.alertBody = self.content.body;
	localNotefication.applicationIconBadgeNumber = self.content.badgeNumber;
	localNotefication.soundName = self.content.soundName ? self.content.soundName : UILocalNotificationDefaultSoundName;
	NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
	userInfo[@"identifier"] = self.identifier;
	if (self.content.userInfo) {
		[userInfo addEntriesFromDictionary:self.content.userInfo];
	}
	localNotefication.userInfo = [NSDictionary dictionaryWithDictionary:userInfo];
	if (self.trigger.region) {
		localNotefication.region = self.trigger.region;
		localNotefication.regionTriggersOnce = !self.trigger.repeats;
	} else if (self.trigger.dateComponents) {
		localNotefication.timeZone = self.trigger.dateComponents.timeZone;
		if (self.trigger.repeats) {
			localNotefication.fireDate = [self.trigger.dateComponents.calendar nextDateAfterDate:[NSDate date] matchingComponents:self.trigger.dateComponents options:0];
			localNotefication.repeatCalendar = self.trigger.dateComponents.calendar;
			NSUInteger repeatInterval = 0;
			for (id component in [DateUtils mappingCalendarUnitToDateComponentProperty].allKeys) {
				repeatInterval = repeatInterval | [self.trigger.dateComponents valueForComponent:component];
			}
			localNotefication.repeatInterval = repeatInterval;
		} else {
			localNotefication.fireDate = self.trigger.dateComponents.date;
		}
	} else if (self.trigger.timeInterval > 0) {
		localNotefication.fireDate = [NSDate dateWithTimeIntervalSinceNow:self.trigger.timeInterval];
		localNotefication.timeZone = self.trigger.dateComponents.timeZone;
		if (self.trigger.repeats) {
			localNotefication.repeatCalendar = self.trigger.dateComponents.calendar;
			localNotefication.repeatInterval = NSCalendarUnitSecond;
		}
	}
	return localNotefication;
}

@end

@interface UserNotificationsManager ()<UNUserNotificationCenterDelegate>
@end

@implementation UserNotificationsManager

+ (void)load {
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
		if (NSClassFromString(@"UNUserNotificationCenter")) {
			UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
			center.delegate = [self sharedManager];
		}
	});
}

#pragma mark - Private

+ (instancetype)sharedManager {
	static dispatch_once_t onceToken;
	static UserNotificationsManager *instance;
	dispatch_once(&onceToken, ^{
		instance = [[self alloc] init];
	});
	return instance;
}

#pragma mark - Public

+ (BOOL)authorizeUserNotifications {
	__block BOOL flag = NO;
	if (NSClassFromString(@"UNUserNotificationCenter")) {
		UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
		__block BOOL notDetermined = NO;
		if (!notDetermined) {
			dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
			[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) {
				if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
					notDetermined = YES;
				} else {
					if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
						if (settings.alertSetting == UNNotificationSettingEnabled) {
							flag = YES;
						}
					}
				}
				dispatch_semaphore_signal(semaphore);
			}];
			dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
		}
		if (notDetermined) {
			dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
			[center requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError *error) {
				if (granted) {
					flag = YES;
				}
				dispatch_semaphore_signal(semaphore);
			}];
			dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
		}
	} else {
		[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]];
		if ([UIApplication sharedApplication].currentUserNotificationSettings.types & UIUserNotificationTypeAlert) {
			flag = YES;
		}
	}
	return flag;
}

#pragma mark - local notification

+ (void)addNotificationRequest:(NMNotificationRequest *)request {
	if (NSClassFromString(@"UNUserNotificationCenter")) {
		UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
		[center addNotificationRequest:[request _transformToUNNotificationRequest] withCompletionHandler:nil];
	} else {
		[[UIApplication sharedApplication] scheduleLocalNotification:[request _transformToUILocalNotification]];
	}
}

+ (void)removeAllPendingNotificationRequests {
	if (NSClassFromString(@"UNUserNotificationCenter")) {
		UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
		[center removeAllPendingNotificationRequests];
	} else {
		[[UIApplication sharedApplication] cancelAllLocalNotifications];
	}
}

#pragma mark - remote notification

#pragma mark - User notification center delegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
	// foreground -- ios10,autoexec
	UNNotificationPresentationOptions options = UNNotificationPresentationOptionNone;
	if (notification.request.content.badge) {
		// options = options | UNNotificationPresentationOptionBadge;
	}
	if (notification.request.content.sound) {
		options = options | UNNotificationPresentationOptionSound;
	}
	if (notification.request.content.title || notification.request.content.body) {
		options = options | UNNotificationPresentationOptionAlert;
	}
	[AppLocalConfig sharedInstance].hasUnreadMessage = YES;
	[[NSNotificationCenter defaultCenter] postNotificationName:UnreadMessageNotification object:nil];
	completionHandler(options);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
	// background -- ios10,checkexec
	[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
	[AppLocalConfig sharedInstance].hasUnreadMessage = YES;
	[[NSNotificationCenter defaultCenter] postNotificationName:UnreadMessageNotification object:nil];
	if (self.handler) {
		self.handler(response);
	}
	completionHandler();
}

@end
