//
//  UniversalSDK.m
//  Unity-iPhone
//
//  Created by 蔡瀚 on 2018/4/24.
//

#import "UniversalSDK.h"
#import "JPUSHService.h"
#import "AdSupport/AdSupport.h"
#import "opus.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif
#import "SystemConfiguration/CaptiveNetwork.h"
#import "XHAuxiliarySDK.h"
#import "XHAuxiliaryHeader.h"
#import "XHAuxiliaryUserAccount.h"

@interface UniversalSDK()<JPUSHRegisterDelegate,UIWebViewDelegate,XHAuxiliaryDelegate>
@end

@implementation UniversalSDK

#define CHANNEL_NUM 1

static int s_frequency = 16000;
static int s_bitRate = 20000;
static int s_bandMode = OPUS_BANDWIDTH_WIDEBAND;
static int s_frameSize = 160;
static int sBatteryLevel = -1;
static int sBatteryState = -1;
static NSThread * _thread;
static NSString* APP_ID;

-(void) Init
{
    UIDevice *_device = [UIDevice currentDevice];
    _device.batteryMonitoringEnabled = true;
    
    NSString* _uniqueID = [[NSUserDefaults standardUserDefaults] objectForKey:@"tsw_unique_id"];
    //获取IDFA
    NSString* _idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    
    if(_uniqueID == NULL || [_uniqueID length] <= 0)
    {
        //判断IDFA是否为空
        BOOL isEmpty = [[_idfa stringByReplacingOccurrencesOfString:@"-" withString:@""] stringByReplacingOccurrencesOfString:@"0" withString:@""].length;
        if (isEmpty) {
            //不为空，将IDFA作为唯一标识
            _uniqueID = _idfa;
        }
        else {
            //为空，获取UUID作为唯一标识
            _uniqueID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        }
        
        //保存唯一设备标识,如已存在则不进行任何处理
        [[NSUserDefaults standardUserDefaults] setObject:_uniqueID forKey:@"tsw_unique_id"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    // 取得UserAgent
    UIWebView* _webView = [[UIWebView alloc] initWithFrame:CGRectZero];
    NSString* _userAgent = [_webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
    
    // 发送设备信息
    NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                  _uniqueID,@"unique_id",
                                  _idfa,@"android_id",
                                  [NSNumber numberWithInt:S2U_DeviceInfo],@"code",
                                  _userAgent,@"userAgent",nil];
    [self SendMessageToUnity:_dict];
    
    // 自由sdk初始化
    [self FreeSDKInit];
    
    // 发送个推id
    [_dict removeAllObjects];
    [_dict setObject:[JPUSHService registrationID] forKey:@"clientID"];
    [_dict setObject:[NSNumber numberWithInt:S2U_PushClientID] forKey:@"code"];
    [self SendMessageToUnity:_dict];
    
    // 发送初始化完成
    [_dict removeAllObjects];
    [_dict setObject:[NSNumber numberWithInt:S2U_SdkInitComplete] forKey:@"code"];
    [_dict setObject:@"js" forKey:@"channelPlatform"];
    [self SendMessageToUnity:_dict];
}

-(void)SendMessageToUnity:(NSDictionary*)dict
{
    BOOL _result = [NSJSONSerialization isValidJSONObject:dict];
    if(_result)
    {
        NSData* _jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:NULL];
        UnitySendMessage(UNITY_OBJ_NAME, UNITY_FUNC_NAME,
                         [[[NSString alloc] initWithData:_jsonData encoding:NSUTF8StringEncoding] UTF8String]);
    }
}

-(void) FreeSDKInit {
    /* 初始化SDK */
    [XHAuxiliarySDK setDelegate:self];
    
    [[XHAuxiliarySDK defaultXHAuxiliary] XHAuxiliarySDKInitWithAPPID:@"1075" Completion:^(XHAuxiliaryInitErrorCode result) {
        
        if (result == XHAuxiliaryInitErrorCodeNone) {
            //            初始化SDK成功
            NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:S2U_FreePlatformInitOk],@"code",nil];
            [self SendMessageToUnity:_dict];
        }else if (result == XHAuxiliaryInitErrorCodeConig){
            //            配置信息有误
            NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:S2U_FreePlatformInitFail],@"code",nil];
            [self SendMessageToUnity:_dict];
        }else if(result == XHAuxiliaryInitErrorCodeNet){
            //            网络错误
            NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:S2U_FreePlatformInitFail],@"code",nil];
            [self SendMessageToUnity:_dict];
        }else{
            //            游戏更新中
            NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:S2U_FreePlatformInitFail],@"code",nil];
            [self SendMessageToUnity:_dict];
        }
        
    }];
}


- (void)accountLoginResult:(XHAuxiliaryToolStatus)result User:(XHAuxiliaryUserAccount *)model{
    
    if(result == XHAuxiliary_SUCCESS){
        
        NSLog(@"token = %@, uid = %@",model.accountToken,model.accountUid);
        NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                               [NSDictionary dictionaryWithObjectsAndKeys:model.accountToken, @"token",
                                model.accountUid, @"account_id",
                                model.accountUid, @"account", nil],@"info",
                               [NSNumber numberWithInt:S2U_FreePlatformLoginOk], @"code", nil];
        [self SendMessageToUnity:_dict];
    }
}

- (void)toolResult:(XHAuxiliaryToolStatus)result data:(id)data{
    if (result == XHAuxiliary_SUCCESS) {
        NSLog(@"成功%@",data);
    }else{
        NSLog(@"错误");
    }
}

-  (void)appstoreResult:(XHAuxiliaryToolStatus)result data:(id)data{
    
    if (result == XHAuxiliary_SUCCESS) {
        NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithInt:S2U_FreePlatformPayOk],@"code",nil];
        [self SendMessageToUnity:_dict];
    }else if (result == XHAuxiliary_CANCEL){
        NSLog(@"取消  %@",data);
        NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithInt:S2U_FreePlatformLoginCancel],@"code",nil];
        [                         self SendMessageToUnity:_dict];
    }else if (result == XHAuxiliary_UNKNOW){
        NSLog(@"错误  %@",data);
        NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithInt:S2U_FreePlatformPayFail],@"code",nil];
        [                         self SendMessageToUnity:_dict];
    }
    
}

-(void) BatteryThread {
    while (TRUE)
    {
        [NSThread sleepForTimeInterval:1];
        
        UIDevice *_device = [UIDevice currentDevice];
        
        int _state = [_device batteryState];
        if(_state != sBatteryState){
            sBatteryState = _state;
            NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:sBatteryState], @"status",
                                   [NSNumber numberWithInt:S2U_BatteryCharging], @"code", nil];
            
            [self SendMessageToUnity:_dict];
        }
        
        int _level = (int)([_device batteryLevel] * 100);
        if(_level != sBatteryLevel){
            sBatteryLevel = _level;
            NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:sBatteryLevel], @"level",
                                   [NSNumber numberWithInt:S2U_BatteryLevel], @"code", nil];
            
            [self SendMessageToUnity:_dict];
        }
    }
}

-(void) OpenURL:(NSString*) url {
    
    if(m_UIWebView != NULL) {
        [self btnClick:NULL];
        return;
    }
    
    CGRect _bounds = UnityGetMainWindow().bounds;
    
    float _scale = _bounds.size.width / 1334;
    
    float _width = 982 * _scale;
    float _height = 560 * _scale;
    
    float _offsetX = (_bounds.size.width - _width) * .5f;
    float _offsetY = (_bounds.size.height - _height) * .5f;
    
    m_UIWebView = [[UIWebView alloc] initWithFrame:CGRectMake(_offsetX, _offsetY, _width, _height)];
    m_UIWebView.delegate = self;
    m_UIWebView.scalesPageToFit = YES ;
    m_UIWebView.scrollView.scrollEnabled = YES;
    m_UIWebView.scrollView.bounces = NO;
    NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    [m_UIWebView loadRequest:request];
}

-(void) btnClick:(UIButton*)sender {
    [m_CloseBtn removeFromSuperview];
    [m_CloseBtn removeTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    m_CloseBtn = NULL;
    
    NSURLCache *_cache = [NSURLCache sharedURLCache];
    [_cache removeAllCachedResponses];
    [_cache setDiskCapacity:0];
    [_cache setMemoryCapacity:0];
    
    [m_UIWebView removeFromSuperview];
    m_UIWebView = NULL;
}

-(void)webViewDidStartLoad:(UIWebView *)webView{
}

-(void)webViewDidFinishLoad:(UIWebView *)webView{
    
    [UnityGetMainWindow().rootViewController.view addSubview:m_UIWebView];
    CGRect _bounds = UnityGetMainWindow().bounds;
    
    float _scale = _bounds.size.width / 1334;
    
    float _width = 982 * _scale;
    float _height = 560 * _scale;
    
    m_CloseBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [m_CloseBtn setFrame:CGRectMake(_width - 455 * _scale, _height - 86 * _scale, 180 * _scale, 72 * _scale)];
    [m_CloseBtn setTitle:@"我知道了" forState:UIControlStateNormal];
    
    NSString *_bundlePath = [[NSBundle mainBundle] pathForResource:@"The2thWorldRES.bundle" ofType:nil];
    NSBundle *_bundle = [NSBundle bundleWithPath:_bundlePath];
    NSString *pic1Path = [_bundle pathForResource:@"TY_AN_34.png" ofType:nil];
    
    [m_CloseBtn setBackgroundImage:[UIImage imageWithContentsOfFile:pic1Path] forState:UIControlStateNormal];
    [m_CloseBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [m_CloseBtn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    
    [m_UIWebView addSubview:m_CloseBtn];
}

-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
}

-(void)JPushInit:(NSDictionary*)launchOptions {
    
    NSString *_bundlePath = [[NSBundle mainBundle] pathForResource:@"The2thWorldRES.bundle" ofType:nil];
    NSString* _configPath = [[NSBundle bundleWithPath:_bundlePath] pathForResource:@"The2thWorldSDKConfig" ofType:@"plist"];
    NSMutableDictionary *_configDict = [[NSMutableDictionary alloc] initWithContentsOfFile:_configPath];
    
    JPUSHRegisterEntity *_entity = [[JPUSHRegisterEntity alloc] init];
    _entity.types = JPAuthorizationOptionAlert | JPAuthorizationOptionBadge | JPAuthorizationOptionSound;
    if([[UIDevice currentDevice].systemVersion floatValue] > 8.0){
    }
    
    [JPUSHService registerForRemoteNotificationConfig:_entity
                                             delegate:self];
    [JPUSHService setupWithOption:launchOptions
                           appKey:_configDict[@"JPush_AppKey"]
                          channel:@"develop"
                 apsForProduction:JPush_IsProduction
            advertisingIdentifier:nil];
}

- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    completionHandler();
}

- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
    
    NSDictionary * userInfo = notification.request.content.userInfo;
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    completionHandler(UNNotificationPresentationOptionAlert);
}

-(id) APNativeJSONObject:(NSData *)data{
    if (!data) {
        return nil;
    }
    
    NSError *error = nil;
    id retId = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    
    if (error) {
        NSLog(@"%s trans data to obj with error: %@", __func__, error);
        return nil;
    }
    
    return retId;
}

-(NSData *)APNativeJSONData:(id)obj {
    NSError *error = nil;
    NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:0 error:&error];
    if (error) {
        NSLog(@"%s trans obj to data with error: %@", __func__, error);
        return nil;
    }
    return data;
}

-(void) RemoveLocalNotificationWithIdentifierKey:(NSString*) idKey{
    JPushNotificationIdentifier *identifier = [[JPushNotificationIdentifier alloc] init];
    identifier.identifiers = @[idKey];
    identifier.delivered = YES;  //iOS10以上有效，等于YES则在通知中心显示的里面移除，等于NO则为在待推送的里面移除；iOS10以下无效
    [JPUSHService removeNotification:identifier];
}

-(void)HandleUnityMessage:(NSString *)json {
    
    NSLog(@"收到Unity发来的消息 => %@", json);
    
    NSData *_jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *_dict = [self APNativeJSONObject:_jsonData];
    
    switch([[_dict objectForKey:@"code"] intValue]){
        case U2S_Init:
            [self Init];
            APP_ID = [_dict objectForKey:@"appID"];
            break;
        case U2S_CopyContent:
            [UIPasteboard generalPasteboard].string = _dict[@"content"];
            break;
        case U2S_FreePlatformInit:
        {
            [self FreeSDKInit];
        }
            break;
        case U2S_MakeKeyAndVisible:
        {
            UIWindow * _window = [[UIApplication sharedApplication].delegate window];
            if (_window != nil && _window.rootViewController != nil) {
                [_window makeKeyAndVisible];
            }
        }
            break;
        case U2S_OpenWebView:
            [self OpenURL:_dict[@"url"]];
            break;
        case U2S_FreePlatformLogin:
        {
            int i = [[XHAuxiliarySDK defaultXHAuxiliary] XHAuxiliaryLoginInView:UnityGetMainWindow().rootViewController.view];
            
            if (i == 0) {
                /* 成功 */

            }else{
                NSLog(@"尚未初始化SDK");
            }
            
        }
            break;
        case U2S_FreePlatformLogout:
        {
            if ([XHAuxiliarySDK defaultXHAuxiliary].isLogined == YES) {
                [[XHAuxiliarySDK defaultXHAuxiliary] LLLogout];
                NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                                       [NSNumber numberWithInt:S2U_FreePlatformLogoutOk], @"code", nil];
                
                [self SendMessageToUnity:_dict];
            }else{
                NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                                       [NSNumber numberWithInt:S2U_FreePlatformLogoutFail], @"code", nil];
                
                [self SendMessageToUnity:_dict];
                NSLog(@"尚未登录，注销失败！");
            }
            break;
        }
        case U2S_FreePlatformPay:
        {
            NSString* _roleName = [_dict objectForKey:@"roleName"];
            _roleName = [_roleName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
            NSMutableString* _temp = [[NSMutableString alloc] initWithString:_roleName];
            _roleName = [_temp stringByReplacingOccurrencesOfString:@"\u0000" withString:@""];
            
            NSString* _extraData = [NSString stringWithFormat:@"{\"appid\":\"%@\",\"cpinfo\":\"%@\",\"cporderid\":\"%@\"}",
                                   APP_ID,
                                   [_dict objectForKey:@"cpInfo"],
                                   [_dict objectForKey:@"orderId"]];
            
            [[XHAuxiliarySDK defaultXHAuxiliary] tool:[_dict objectForKey:@"orderId"]
                                      andWithLLItemID:[_dict objectForKey:@"cpInfo"]
                                       andWithLLItemP:[[_dict objectForKey:@"mount"] intValue] * 100
                                    andWithLLReserved:_extraData
                                        andWithLLDesc:[_dict objectForKey:@"title"]];
            
            NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithInt:S2U_FreePlatformLoginCancel],@"code",nil];
            [self SendMessageToUnity:_dict];
            
        }
            break;
        case U2S_PayFinished:
            break;
        case U2S_BatteryListenStart:
        {
            if(_thread == NULL)
            {
                _thread = [[NSThread alloc] initWithTarget:self selector:@selector(BatteryThread) object:nil];
                [_thread setName:@"BatteryCheck"];
            }
            if(![_thread isExecuting])
            {
                [_thread start];
            }
        }
            break;
        case U2S_BatteryListenStop:
            break;
        case U2S_JPushRemoveLocalMessage:
            [self RemoveLocalNotificationWithIdentifierKey:_dict[@"id"]];
            break;
        case U2S_JPushAddLocalMessage:
        {
            JPushNotificationContent *_content = [[JPushNotificationContent alloc] init];
            if (_dict[@"title"]) {
                _content.title = _dict[@"title"];
            }
            if (_dict[@"subtitle"]) {
                _content.subtitle = _dict[@"subtitle"];
            }
            if (_dict[@"content"]) {
                _content.body = _dict[@"content"];
            }
            if (_dict[@"badge"]) {
                _content.badge = @([_dict[@"badge"] intValue]);
            }
            if (_dict[@"action"]) {
                _content.action = _dict[@"action"];
            }
            if (_dict[@"extra"]) {
                _content.userInfo = _dict[@"extra"];
            }
            if (_dict[@"sound"]) {
                _content.sound = _dict[@"sound"];
            }
            JPushNotificationTrigger *_trigger = [[JPushNotificationTrigger alloc] init];
            if (_dict[@"fireTime"]) {
                long _time = [_dict[@"fireTime"] longValue];
                NSNumber *date = @(_time);
                if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
                    NSTimeInterval currentInterval = [[NSDate date] timeIntervalSince1970];
                    NSTimeInterval interval = [date doubleValue] - currentInterval;
                    interval = interval > 0? interval : 0;
                    _trigger.timeInterval = interval;
                } else {
                    _trigger.fireDate = [NSDate dateWithTimeIntervalSince1970: [date doubleValue]];
                }
                JPushNotificationRequest *_request = [[JPushNotificationRequest alloc] init];
                _request.requestIdentifier = [NSString stringWithFormat:@"%@",_dict[@"id"]];
                _request.content = _content;
                _request.trigger = _trigger;
                _request.completionHandler = ^(id result) {
                    // iOS10以上成功则result为UNNotificationRequest对象，失败则result为nil;iOS10以下成功result为UILocalNotification对象，失败则result为nil
                    NSLog(@"结果返回：%@", result);
                };
                [JPUSHService addNotification:_request];
                break;
            }
        }
    }
}
@end

extern "C" void native_opus_init(int frequency, int bitRate, int bandMode)
{
    s_frequency = frequency;
    s_bandMode = bandMode;
    s_bitRate = bitRate;
    s_frameSize = frequency / 100;
}

extern "C" int native_opus_encode(opus_int16 *pcm, int len, unsigned char *opus)
{
    int errorCode = 0;
    opus_int32 skip = 0;
    OpusEncoder *enc = opus_encoder_create(s_frequency, CHANNEL_NUM, OPUS_APPLICATION_VOIP, &errorCode);
    if (OPUS_OK != errorCode) {
        enc = NULL;
        return -1;
    }
    
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(s_bandMode));
    opus_encoder_ctl(enc, OPUS_SET_BITRATE(s_bitRate));
    opus_encoder_ctl(enc, OPUS_SET_VBR(1));
    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10));
    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(0));
    opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(OPUS_SIGNAL_VOICE));
    opus_encoder_ctl(enc, OPUS_SET_DTX(0));
    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(0));
    opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
    opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
    
    unsigned char *rbytes = opus;
    opus_int16 *frame = pcm;
    int totalSize = 0;
    while (len >= s_frameSize)
    {
        opus_int32 length = opus_encode(enc, frame, s_frameSize, rbytes + sizeof(char), s_bitRate);
        rbytes[0] = length;
        frame += s_frameSize;
        rbytes += length + sizeof(char);
        len -= s_frameSize;
        totalSize += length;
    }
    opus_encoder_destroy(enc);
    return totalSize;
}

extern "C" int native_opus_decode(unsigned char *opus, int len, short *pcm)
{
    int err = 0;
    //opus_int32 skip = 0;
    
    OpusDecoder *dec = opus_decoder_create(s_frequency, CHANNEL_NUM, &err);
    if (err != OPUS_OK) {
        dec = NULL;
        return -1;
    }
    
    while (len > 0)
    {
        int frame_opus_length = opus[0];
        int length = opus_decode(dec, opus + sizeof(char), frame_opus_length, pcm, s_frameSize, 0);
        opus += sizeof(char) + frame_opus_length;
        pcm += s_frameSize;
        len = len - frame_opus_length - sizeof(char);
    }
    opus_decoder_destroy(dec);
    return 0;
}
