//
//  AppDelegate+RemotePush.m
//  Gengmei
//
//  Created by 翟国钧 on 15/5/8.
//  Copyright (c) 2015年 Wanmeichuangyi. All rights reserved.
//
#import <GMCache/GMCache-umbrella.h>
#import "AppDelegate+handleSchemeURL.h"

// 引入JPush功能所需头文件
//#import <JPush/JPUSHService.h>
// iOS10注册APNs所需头文件
#import "JPUSHService.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif
//#import "Gengmei-Swift.h"
#import "WMNetService.h"
//#import "GMConversationDetailController.h"
//#import "GMCustomerServiceDetailViewController.h"
//#import "UIViewController+UrlScheme.h"
#import <objc/runtime.h>
#import "GMLoginManager.h"
#import "GMNotificationName.h"
#import "GMPushCtrlObject.h"
#import "GMPushMsgObject.h"
#import "GMPushObject.h"

/**
 管理iOS 10 应用前台时的推送接收与交互
 */
@interface GMNotificationHandler: NSObject <JPUSHRegisterDelegate>
@end

#pragma mark - AppDelegate
@interface AppDelegate ()
@property (nonatomic, readonly) GMNotificationHandler *notificationHandler;
@end


@implementation AppDelegate (RemotePush)

- (void)setLaunchOptions:(NSDictionary *)options {
    objc_setAssociatedObject(self, @selector(launchOptions), options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDictionary *)launchOptions {
    return objc_getAssociatedObject(self, @selector(launchOptions));
}

- (GMNotificationHandler *)notificationHandler {
    GMNotificationHandler *handler = objc_getAssociatedObject(self, @selector(notificationHandler));
    if (handler == nil) {
        handler = [GMNotificationHandler new];
        objc_setAssociatedObject(self, @selector(notificationHandler), handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return handler;
}


#pragma mark - 推送处理
/**
 如果从远程推送启动，在首页加载完成时，push 远程推送指定的页面
 只有在应用从远程推送启动才会走这儿，从后台唤醒不会走这儿
 @author 汪洋 16-08-09 in 6.3.0
 */
- (void)manageLaunchOptions {
    if (![AppDelegate shareInstance].launchOptions) {
        return;
    }
    NSDictionary *remoteNotification = [AppDelegate shareInstance].launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
    [self manageRemoteNotification:remoteNotification];
}
#pragma mark - 2018.11.19-->zhouLiang注释
- (void)manageRemoteNotification:(NSDictionary *)notification {
    // 如果tabBarController没有加载，那么直接返回
//    if (!AppDelegate.isTabBarControllerShown) {
//        return;
//    }
//    [[NSNotificationCenter defaultCenter] postNotificationName:READ_NEW_MESSAGE object:nil userInfo:notification[@"message"]];
    // 如果推送没有被deley，则需要立即清除launchOptions，以免在首页造成二次调用
    [AppDelegate shareInstance].launchOptions = nil;
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    
    GMPushObject *pushInfo = [[GMPushObject alloc] initWithDictionary:notification];
    debugLog(@"pushInfo.pushUrl%@", pushInfo.pushUrl);
    switch (pushInfo.type) {
            // 普通推送
        case GMPushTypeDefault: {
            if ([pushInfo.pushUrl isNonEmpty]) {
                [AppDelegate.visibleController pushScheme:pushInfo.pushUrl];
            }
            break;
        }
            // 控制类型消息
        case GMPushTypeCtrl: {
            //防止未登录情况下 一直弹出登陆提示
//            if ([AppDelegate.visibleController isKindOfClass:[GMSignInController class]] && [GMLoginManager shareInstance].isVisitor) {
//                return;
//            }
            // 下面的一段代码应该放在GMConversation中
//            GMPushCtrlObject *ctrl = [[GMPushCtrlObject alloc] initWithDictionary:pushInfo.ctrl error:NULL];
//            if (!ctrl) {
//                return;
//            }
//            [self didReceiveCustomerServicePushWithUserKey:pushInfo];
            break;
        }
            // 普通消息推送
        case GMPushTypeMsg: {
            //防止未登录情况下 一直弹出登陆提示
//            if ([AppDelegate.visibleController isKindOfClass:[GMSignInController class]] && [GMLoginManager shareInstance].isVisitor) {
//                return;
//            }
            // 下面的一段代码应该放在GMConversation中
            GMPushMsgObject *msg = [[GMPushMsgObject alloc] initWithDictionary:pushInfo.msg error:NULL];
            if (msg.conversationType == GMPushMsgTypeNormal) {
                [self didReceiveConversationPushWithUserKey:pushInfo];
            } else if (msg.conversationType == GMPushMsgTypeCustomerService) {
                [self didReceiveCustomerServicePushWithUserKey:pushInfo];
            }
            break;
        }
        default:
            break;
    }
}

- (void)didReceiveCustomerServicePushWithUserKey:(GMPushObject *)pushInfo {
//    GMCustomerServiceDetailViewController *controller = (GMCustomerServiceDetailViewController *)AppDelegate.visibleController;
//    GMPushMsgObject *msg = [[GMPushMsgObject alloc] initWithDictionary:pushInfo.msg error:NULL];
//    if ([controller isMemberOfClass:[GMCustomerServiceDetailViewController class]] && [controller.viewModel.userKey isEqualToString:msg.userKey]) {
//        //刷新当前页面
//        [[NSNotificationCenter defaultCenter] postNotificationName:NEED_REFRESH_CONVERSIONS object:nil userInfo:pushInfo.msg];
//
//    } else {
//        GMCustomerServiceDetailViewController *cc = [[GMCustomerServiceDetailViewController alloc] init];
//        cc.viewModel.lastMsgId = 0;
//        cc.viewModel.userKey = msg.userKey;
//        [AppDelegate.navigation pushViewController:cc animated:YES];
//    }
}

- (void)didReceiveConversationPushWithUserKey:(GMPushObject *)pushInfo {
//    GMPushMsgObject *msg = [[GMPushMsgObject alloc] initWithDictionary:pushInfo.msg error:NULL];
//    GMCustomerServiceDetailViewController *controller = (GMCustomerServiceDetailViewController *)AppDelegate.visibleController;
//    if ([controller isMemberOfClass:[GMConversationDetailController class]] && [controller.viewModel.userKey isEqualToString:msg.userKey]) {
//      [[NSNotificationCenter defaultCenter] postNotificationName:NEED_REFRESH_CONVERSIONS object:nil userInfo:pushInfo.msg];
//    } else {
//        BOOL isDetail = NO;
//        if ([controller isMemberOfClass:[GMConversationDetailController class]]) {
//            isDetail = YES;
//        }
//        GMConversationDetailController *cc = [[GMConversationDetailController alloc] init];
//        cc.viewModel.userKey = msg.userKey;
//        if (isDetail) {
//            [AppDelegate.visibleController push:cc andKillTo:[GMConversationDetailController class] further:1];
//        } else {
//            [AppDelegate.navigation pushViewController:cc animated:YES];
//        }
//    }
}

#pragma mark - 推送是否被授权
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [self trackUserGranted:notificationSettings.types != UIUserNotificationTypeNone];
}

- (void)trackUserGranted:(BOOL)granted {
    NSString *haveShowAuthorNotifation = [GMCache fetchObjectAtDocumentPathWithkey:kHaveShowPushAuthorizeAlert];
    /** 第一次打开APP设置通知授权 **/
    if (!haveShowAuthorNotifation) {
        [Phobos track:@"permit_push_notification" attributes:@{@"status":granted ? @(1) : @0}];
        [GMCache storeObjectAtDocumentPathWithkey:kHaveShowPushAuthorizeAlert object:kHaveShowPushAuthorizeAlert];
    }
}

#pragma mark - 推送配置
- (BOOL)remoteNotificationsGranted {
    // enabledRemoteNotificationTypes
    return [UIApplication sharedApplication].registeredForRemoteNotifications;
}

- (void)setupJPushIfAllowed {
    // 只在授权通过了。app第一次安装由于没有授权，会走UIViewController+PopView中的showNotificationAuthorizeIfNeeded
//    if ([self remoteNotificationsGranted]) {
        [self setupJPushNotification];
//    }
}

/**
 @param launchOptions App 启动参数
 */
- (void)setupJPushNotification {
    // 是否弹起了系统通知框
    [GMCache storeObjectAtDocumentPathWithkey:kHasShowSystemPushAuthorizeNotification object:kHasShowSystemPushAuthorizeNotification];
    
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
        if (@available(iOS 10.0, *)) {
            entity.types = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
        } else {
            // Fallback on earlier versions
        }
        [JPUSHService registerForRemoteNotificationConfig:entity delegate:self.notificationHandler];
        if (@available(iOS 10.0, *)) {
            [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:entity.types completionHandler:^(BOOL granted, NSError * _Nullable error) {
                [self trackUserGranted:granted];
            }];
        } else {
            // Fallback on earlier versions
        }
    } else {
        //可以添加自定义categories
        [JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
                                                          UIUserNotificationTypeSound |
                                                          UIUserNotificationTypeAlert)
                                              categories:nil];
    }
    [JPUSHService setupWithOption:self.launchOptions appKey:JPUSHKEY channel:@"Publish channel" apsForProduction:NO];
#ifndef DEBUG
    [JPUSHService setLogOFF];
#endif
}

/**
 * 将16进制的数据转换成为hex data
 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSMutableString* str = [NSMutableString stringWithCapacity:[deviceToken length] * 2];
    const unsigned char* bytes = (const unsigned char*)[deviceToken bytes];
    for (int i = 0; i < [deviceToken length]; i++) {
        [str appendFormat:@"%02x", bytes[i]];
    }
    // 读取用户信息, 并且设置deviceToken
    [GMLoginManager shareInstance].user.deviceToken = (str.length > 0) ? str : @"";
    [JPUSHService registerDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError: (NSError *)error { }

/**
 1. 从远程推送启动app不会走这里。
 2. 应用前台时收到推送会立即走这个方法
 3. 应用后台时收到推送不会走这个方法，只有用户点击了推送，才会走这个方法，iOS9 及以前会走这个方法 iOS 10 jpushNotificationCenter 走这个方法
 @author 汪洋 16-08-09 in 6.3.0
 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [JPUSHService handleRemoteNotification:userInfo];
    NSLog(@"didReceiveRemoteNotification");
    
    // 只有点击 notification 应用从后台进入前台时，才会走下面的判断。将app push到某个页面
    if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive)) {
        [self manageRemoteNotification:userInfo];
    } else {
        [self manageForegroundPush:userInfo];
    }
}

- (void)manageForegroundPush:(NSDictionary *)userInfo {
    // 应用前台时
    // 下面的一段代码应该放在GMConversation中
    GMPushObject *pushInfo = [[GMPushObject alloc] initWithDictionary:userInfo];
    if ((pushInfo.type == GMPushTypeMsg) && ![GMLoginManager shareInstance].isVisitor) {
        GMPushMsgObject *msg = [[GMPushMsgObject alloc] initWithDictionary:pushInfo.msg error:NULL];
        if (msg.conversationType == GMPushMsgTypeNormal) {

        } else if (msg.conversationType == GMPushMsgTypeCustomerService) {
//            [[NSNotificationCenter defaultCenter] postNotificationName:NEED_REFRESH_CUSTOMERSERVICE object:nil userInfo:pushInfo.msg];
        }
    }
}
#pragma mark-  判断用户是否允许推送
- (BOOL)userIsAllowPush {
    if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone ) {
        return NO;
    } else {
        return YES;
    }
}
@end


@implementation GMNotificationHandler
// 详细参考http://www.tuicool.com/articles/vIfMJfq
/**
 应用前台时收到推送会走这个方法，我们可以作一些额外的处理，并且在最后决定是否显示该通知
 iOS 10 Support
 */
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler  API_AVAILABLE(ios(10.0)){
    NSDictionary * userInfo = notification.request.content.userInfo;
    if (@available(iOS 10.0, *)) {
        if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
            [JPUSHService handleRemoteNotification:userInfo];
        }
    } else {
        // Fallback on earlier versions
    }
    [[AppDelegate shareInstance] manageForegroundPush:userInfo];
    
    // 需要执行这个方法，选择是否提醒用户，有Badge、Sound、Alert三种类型可以选择设置
    // 如果不想显示某个通知，可以直接用空 options 调用 completionHandler:
    // completionHandler([])
    if (@available(iOS 10.0, *)) {
        completionHandler(UNNotificationPresentationOptionAlert);
    } else {
        // Fallback on earlier versions
    }
}

/**
 无论前台，还是后台
 只要用户与通知进行交互就会被调用，包括通过通知打开了应用，或者点击了某个 action
 @note: iOS 10 Support
 */
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    NSLog(@"didReceiveNotificationResponse");
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    [[AppDelegate shareInstance] manageRemoteNotification:userInfo];
    
    // 客户端点击推送消息的时候的埋点。目前只支持到iOS10，已和成亮确认。用来确认有多少人点击了这个推送。identifier 是由极光生成的
    NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
    [Phobos track:@"notification_open" attributes:@{@"message_id": SafeValue(response.notification.request.identifier), @"open_time": @(interval)}];
    
    // 系统要求执行这个方法
    completionHandler();
}
@end
