//
//  Phobos.m
//  GengmeiDoctor
//
//  Created by Thierry on 16/1/26.
//  Copyright © 2016年 wanmeizhensuo. All rights reserved.
//

#import "Phobos.h"
#import <AdSupport/AdSupport.h>
#import "PhobosUtil.h"
#import "PhobosConfig.h"
#import "UIResponder+PhobosPV.h"
#import "PhobosUtil.h"
#import "PhobosCustomVisibleController.h"
#import "UIDevice+Resolutions.h"
#import <GMCache/GMCache.h>
static Phobos *sharedClient = nil;
static NSString *sdkVersion = @"110";

@interface Phobos ()
@property (strong, nonatomic) UIViewController *visibleController;
@property (strong, nonatomic) NSDateFormatter *dateFormatter;
@property (strong, nonatomic) NSString *appName;
@property (strong, nonatomic) NSString *channelId;
@property (strong, nonatomic) NSString *appVersion;
@property (strong, nonatomic) NSString *sessionId;
/* 每一条埋点数据的物理ID，自增，生命周期和sessionId相同。特别注意：在sessionOver的时候，要把他置为0 */
@property (assign, nonatomic) NSInteger serialId;

// 用来记录除serverAPI以外的API
@property (strong, nonatomic) NSMutableArray *APIArray;

@end

@implementation Phobos

+ (Phobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{
    return [[self alloc] initWithAppName:appName channelId:channelId];
}

+ (Phobos *)sharedClient{
    return sharedClient;
}

+ (void)setSharedClient:(Phobos *)client{
    sharedClient = client;
}

- (instancetype)initWithAppName:(NSString *)appName channelId:(NSString *)channelId{
    self = [super init];
    if (self) {
        _appName = appName;
        _channelId = channelId;
        _logEnabled = NO;
        _userId = @"";
        _netStatus = @"";
        _currentCityId = @"";
        _serverAPI = @"";
        _greyType = @"";
        _userType = [[NSMutableDictionary alloc] initWithCapacity:0];
        _appVersion = [PhobosUtil getAppVersion];
        _APIArray = [NSMutableArray array];
        _signingType = PhobosSigningTypeUndefined;
        [self setupNotification];
        [self handleSessionStart];
        [self synchronizePhobosKey];
        phobosLog(@"starts to orbit");
    }
    return self;
}

/**
 * disk下的PhobosHaveOpenApp只要存在，就把他取出来放到document下(注：当不支持7.6.16版本的时候，干掉这个方法)
 */
- (void)synchronizePhobosKey {
    if ([GMCache fetchObjectAtDiskWithkey:PhobosHaveOpenApp]) {
        NSString *prefePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        prefePath = [NSString stringWithFormat:@"%@/com.tumblr.TMDiskCache.WMCacheShared/%@",prefePath ,PhobosHaveOpenApp];
        NSURL *fileUrl = [NSURL fileURLWithPathComponents:@[prefePath]];
        BOOL written = [NSKeyedArchiver archiveRootObject:PhobosHaveOpenApp toFile:[fileUrl path]];
    }
}

- (void)dealloc{
    if (self) {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
}

- (void)setUserType:(NSMutableDictionary *)userType {
    if (userType == nil && userType.count == 0) {
        return;
    }
    NSArray *newKeys = userType.allKeys;
    NSArray *oldKeys = _userType.allKeys;
    for (NSString *newKey in newKeys) {
        if ([oldKeys containsObject:newKey]) {
            NSString *newValue = [[userType objectForKey:newKey] stringValue];
            NSString *oldValue = [[_userType objectForKey:newKey] stringValue];
            if (![newValue isEqualToString:oldValue]) {
                [_userType setObject:[userType objectForKey:newKey] forKey:newKey];
            }
        } else {
            [_userType setObject:[userType objectForKey:newKey] forKey:newKey];
        }
    }
}

/**
   在APP启动、从后台到前台的时候需要记录device_opened埋点
 */
- (void)handleEventDeviceOpened{

    /** 每次打开APP埋点 **/
    NSDictionary *dict = @{@"build_cpu_abi": [PhobosUtil currentDeviceCPUType],
                           @"cpu_count": [PhobosUtil currentDeviceCPUCount],
                           @"mac_address": [PhobosUtil getMacAddress],
                           @"phone_operator": [PhobosUtil getTelephonyInfo],
                           @"total_memory": [PhobosUtil getTotalMemorySize],
                           @"run_time": [PhobosUtil deviceRunTime],
                           @"uuid": [PhobosUtil deviceId],
                           @"build_version_release": [[UIDevice currentDevice] systemVersion],
                           @"build_model": [UIDevice deviceVersion],
                           };
    [Phobos track:@"device_opened" attributes:dict sendNow:YES];
    
    /** 第一次打开APP埋点 **/
    // 当不再支持7.6.15版本时，只保留
    if (![GMCache fetchObjectAtDocumentPathWithkey:PhobosHaveOpenApp]) {
        [Phobos track:@"device_activated" attributes:@{} sendNow:YES];
        [Phobos track:@"device_activated" attributes:@{} sendNow:NO];
        [GMCache storeObjectAtDocumentPathWithkey:PhobosHaveOpenApp object:PhobosHaveOpenApp];
    }
}

- (UIViewController *)visibleController {
    id target = self.getTopController();

    if ([target conformsToProtocol:NSProtocolFromString(@"PhobosCustomVisibleController")]) {
        target = [target performSelector:@selector(phobosVisibleController)];
    }
    return target;
}

#pragma mark - notification handler
/**
 *  @brief 设置对APP的通知监听
 *
 *  @since 0.0.1
 */
- (void)setupNotification{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAppFinishLaunch:) name:UIApplicationDidFinishLaunchingNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAppInForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAppInBackgound:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}

/**
 *  @brief 每次打开APP或返回前台，即Session开始的时候的处理
 *  @notification didFinishLaunch和willEnterForeground的时候都需要记录
 *
 *  @since 0.0.1
 */
- (void)handleSessionStart{
    _serialId = 0;
    _sessionId = [[NSUUID UUID] UUIDString];

    [GMCache storeObjectAtDocumentPathWithkey:PhobosBeginTime object:[PhobosUtil currentTime]];
}

/**
 *  @brief 应用打开时的处理
 *
 *  @since 0.0.1
 */
- (void)handleAppFinishLaunch:(id)sender{
    phobosLog(@"handleAppFinishLaunch");
    [self handleSessionStart];
    [self handleEventDeviceOpened];
}

/**
 *  @brief 应用进入前台的处理
 *
 *  @since 0.0.1
 */
- (void)handleAppInForeground:(id)sender{
    phobosLog(@"handleAppInForeground");
    [self handleSessionStart];
    [self handleEventDeviceOpened];
    [self fetchDataAndSend];
    [self handlePVEventAppInForeground];
}

/**
 *  @brief 应用进入后台的处理
 *
 *  @since 0.0.1
 */
- (void)handleAppInBackgound:(id)sender{
    phobosLog(@"handleAppInBackgound");
    [self handlePVEventAppInBackgound];
    [self handleSessionOver];
    [self fetchDataAndSend];
}

/**
 *  @brief 会话结束时候的处理
 *
 *  @since 0.0.1
 */
- (void)handleSessionOver{

    //进入后台的同时，把记录时间同步到服务端，把已使用时间清空
    double beginTime = [[GMCache fetchObjectAtDocumentPathWithkey:PhobosBeginTime] doubleValue];
    if (beginTime == 0) {
        return;
    }
    NSDate *date = [NSDate date];
    double endTime = [date timeIntervalSince1970];
    NSString *usedTime = [NSString stringWithFormat:@"%ld",(long)(endTime - beginTime)];
    NSDictionary *dict = @{@"duration":usedTime,
                           @"build_cpu_abi": [PhobosUtil currentDeviceCPUType],
                           @"cpu_count": [PhobosUtil currentDeviceCPUCount],
                           @"mac_address": [PhobosUtil getMacAddress],
                           @"phone_operator": [PhobosUtil getTelephonyInfo],
                           @"total_memory": [PhobosUtil getTotalMemorySize],
                           @"run_time": [PhobosUtil deviceRunTime],
                           @"uuid": [PhobosUtil deviceId],
                           @"build_version_release": [[UIDevice currentDevice] systemVersion],
                           @"build_model": [UIDevice deviceVersion],
                           };
    [Phobos track:@"on_app_session_over" attributes:dict];
    [GMCache removeObjectAtDocumentPathWithkey:PhobosBeginTime];
    //当前session结束之后，把id置为0
    _serialId = 0;
}

/**
 APP从后台到前台的时候，重新初始化pagename等信息
 @author zhaiguojun 16-10-11 in (null)
 */
- (void)handlePVEventAppInForeground {
    if (self.visibleController != nil) {
        [self onPVStart:self.visibleController];
    }
}

/**
 APP进到后台的时候，把当前pageview时间结束
 @author zhaiguojun 16-10-11 in (null)
 */
- (void)handlePVEventAppInBackgound {
    if (self.visibleController != nil) {
        [self onPVEnd:self.visibleController];
    }
}

#pragma mark - track event handler
+ (void)track:(NSString *)eventId{
    [Phobos track:eventId attributes:@{}];
}

+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes{
    [self track:eventId attributes:attributes sendNow:NO];
    NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
    //超过一定数量的话，统一发送一次
    if (array.count > PhobosShardCount) {
        [sharedClient sendArray:array cleanCacheRightNow:YES];
    }
}
+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow{
    NSDictionary *dict = [sharedClient prepareDictionaryForEvent:eventId attributes:attributes];
    @try {
        NSData *JSON = [PhobosUtil encodeJSON:dict];
        if (sendNow) {
            NSArray *array = @[dict];
            // 实时发送的埋点，不能立即清楚缓存
            [sharedClient sendArray:array cleanCacheRightNow:NO];
        }else{
            [sharedClient save:dict];
        }
    
    }
    @catch (NSException *exception) {
        NSAssert(NO, @"哎呀呀,VALUE不能为NSObject ");
    }
   
}

+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes currentAPI:(NSString *)currentAPI {
    [self track:eventId attributes:attributes sendNow:NO currentAPI:currentAPI];
    NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]];
    //超过一定数量的话，统一发送一次
    if (array.count > PhobosShardCount) {
        [sharedClient sendArray:array currentAPI:currentAPI cleanCacheRightNow:YES];
    }
}

+ (void)track:(NSString *)eventId attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI {
    [sharedClient addNewApi:currentAPI]; // 记录新的API
    
    NSDictionary *dict = [sharedClient prepareDictionaryForEvent:eventId attributes:attributes];
    
    @try {
        NSData *JSON = [PhobosUtil encodeJSON:dict];
        if (sendNow) {
            NSArray *array = @[dict];
            // 实时发送的埋点，不能立即清楚缓存
            [sharedClient sendArray:array currentAPI:currentAPI cleanCacheRightNow:NO];
        }else{
            [sharedClient save:dict currentAPI:currentAPI];
        }
        
    }
    @catch (NSException *exception) {
        NSAssert(NO, @"哎呀呀,VALUE不能为NSObject ");
    }
}

+ (void)track:(NSString *)eventId currentAPI:(NSString *)currentAPI {
    [Phobos track:eventId attributes:@{} currentAPI:currentAPI];
}

+ (void)trackJsEvent:(NSString *)jsonString{
    @try {
        NSData *data = [jsonString dataUsingEncoding:NSUnicodeStringEncoding];
        NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        
        id pa = dict[@"params"];
        NSDictionary *json;
        if ([pa isKindOfClass:[NSString class]]) {
            NSError *jsonError;
            NSData *objectData = [pa dataUsingEncoding:NSUTF8StringEncoding];
            json = [NSJSONSerialization JSONObjectWithData:objectData
                                                   options:NSJSONReadingMutableContainers
                                                     error:&jsonError];
            [Phobos track:dict[@"type"] attributes:json];
        }else{
            [Phobos track:dict[@"type"]];
        }
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}

#pragma mark - PV
- (void)onPVStart:(UIResponder<PhobosPVProtocol> *)page {
    // 必须在此处调用一下referer，因为onControllerStart
    [page initReferer];
    [page initRefererLink];
    [page initReferrerIdIfNil];
    [page initReferrerTabName];
    page.inTime = [PhobosUtil currentTime];
}

- (void)onPVEnd:(UIResponder<PhobosPVProtocol> *)page {
    if (![PhobosUtil isNonEmpty:page.pageName] || !page.needLogPV) {
        return;
    }
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    @try {
        [dict setObject:[PhobosUtil currentTime] forKey:@"out"];
        [dict setObject:page.inTime?:@"" forKey:@"in"];
        [dict setObject:page.pageName forKey:@"page_name"];
        [dict setObject:page.businessId?:@"" forKey:@"business_id"];
        [dict setObject:page.referer?:@"" forKey:@"referrer"];
        [dict setObject:page.referrerLink ? : @[] forKey:@"referrer_link"];
        [dict setObject:@(0) forKey:@"fake"];
        [dict setObject:page.referrerId ? : @"" forKey:@"referrer_id"];
        [dict setObject:page.extraParam ? : @"" forKey:@"extra_param"];
        [dict setObject:page.referrerTabName ? : @"" forKey:@"referrer_tab_name"];
        [dict setObject:page.isPush.intValue ? @(page.isPush.intValue) : @(0) forKey:@"is_push"];
        
        if (page.inTime.length > 0) {
            // 页面显示时间为空时不记录页面pv事件
            [Phobos track:@"page_view" attributes:dict];
        }
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}

- (void)simulativePV:(NSString *)pageName businessId:(NSString *)bid referer:(NSString *)referer{
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    @try {
        // fake（模拟）的事件，所以in与out一样，就是这么规定的
        [dict setObject:[PhobosUtil currentTime] forKey:@"in"];
        [dict setObject:[PhobosUtil currentTime] forKey:@"out"];
        [dict setObject:pageName?:@"" forKey:@"page_name"];
        [dict setObject:bid?:@"" forKey:@"business_id"];
        [dict setObject:referer?:@"" forKey:@"referrer"];
        [dict setObject:@(1) forKey:@"fake"];
        
        [Phobos track:@"page_view" attributes:dict];
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}


#pragma mark - 事件存储、发送

/**
 *  @brief 将埋点时间封装成词典数据
 *
 *  @since 0.0.1
 */
- (NSDictionary *)prepareDictionaryForEvent:(NSString *)eventId attributes:(NSDictionary *)attributes{
    NSArray *referrerLink = sharedClient.visibleController.referrerLink;
    if (![eventId isEqualToString:@"page_view"]) {
        NSMutableDictionary *attributesParams = [NSMutableDictionary dictionaryWithDictionary:attributes];
        [attributesParams setValue:referrerLink ? : @[] forKey:@"referrer_link"];
        attributes = attributesParams;
    }
    [self catchNullForEvent:eventId attributes:attributes];
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    @try {
        NSString *currentTime = [PhobosUtil currentTime];
        NSMutableDictionary *deviceParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                             [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString],@"idfa",
                                             [[[UIDevice currentDevice] identifierForVendor] UUIDString],@"idfv",
                                             [PhobosUtil deviceId],@"device_id",
                                             @"ios",@"device_type",
                                             @"Apple",@"manufacturer",
                                             @(self.gps.coordinate.latitude),@"lat",
                                             @(self.gps.coordinate.longitude),@"lng",
                                             _netStatus,@"is_WiFi",
                                             [PhobosUtil getIPAddress:YES],@"ip",nil];
        [deviceParams setValue:_networkStatus forKey:@"net_type"];
        [deviceParams setValue:[UIDevice platform] forKey:@"model"];
        [deviceParams setValue:[UIDevice currentDevice].systemVersion forKey:@"sys_version"];
        NSMutableDictionary *appParams   = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                            _greyType, @"grey_type",
                                            self.appName, @"name",
                                            self.appVersion, @"version",
                                            self.channelId,@"channel",
                                            _userType,@"user_type",
                                            self.currentCityId,@"current_city_id",
                                            @(_serialId++), @"serial_id",nil];
        
        if (_signingType == PhobosSigningTypeDebug || _signingType == PhobosSigningTypeRelease) {
            [dict setObject:@(0) forKey:@"is_release"];
        }
        [dict setObject:eventId forKey:@"type"];
        [dict setObject:appParams forKey:@"app"];
        [dict setObject:sdkVersion forKey:@"version"];
        [dict setObject:deviceParams forKey:@"device"];
        [dict setObject:_userId forKey:@"user_id"];
        [dict setObject:currentTime forKey:@"create_at"];
        [dict setObject:attributes forKey:@"params"];
        [dict setObject:_sessionId forKey:@"app_session_id"];
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
    return dict;
}

/**
 *  @brief 保存数据到缓存层
 *
 *  @param data 数据
 *
 *  @since 0.0.1
 */
- (void)save:(NSDictionary *)data
{
    if (_logEnabled) {
        phobosLog([NSString stringWithFormat:@"save dictionary: %@",data]);
    }

    NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
    if (dataArray) {
#ifdef POD_CONFIGURATION_APP_STORE
        [dataArray addObject:data];
#else
        if (data[@"type"] && [data[@"type"] isEqualToString:@"page_view"]) {
            NSDictionary *pageParams = data[@"params"];
            long long pageInTime = [pageParams[@"in"] longLongValue];
            long long pageOutTime = [pageParams[@"out"] longLongValue];
//            phobosLog(@"pageInTime------%lld",pageInTime);
//            phobosLog(@"pageOutTime------%lld",pageOutTime);
            if (pageInTime && pageOutTime) {
                __block BOOL checkTimeError;
                
                for (int i = 0; i < dataArray.count; i++) {
                    NSDictionary *obj = dataArray[i];
                    
                    if (obj[@"type"] && [obj[@"type"] isEqualToString:@"page_view"]) {
                        NSDictionary *params = obj[@"params"];
                        long long objInTime = [params[@"in"] longLongValue];
                        long long objOutTime = [params[@"out"] longLongValue];
                        if ( (fabsl(objInTime - pageInTime)) < 1 ||  (fabsl(objOutTime - pageOutTime)) < 1) {
                            phobosLog(@"两个埋点inTime 时间差------%f", (fabsl(objInTime - pageInTime)));
                            phobosLog(@"两个埋点outTime 时间差------%f", (fabsl(objOutTime - pageOutTime)));
                            checkTimeError = YES;
                            phobosLog(@"%s____数据校验失败,PV埋点可能重复", __func__);
                            /*
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSString *stringTitle = [NSString stringWithFormat:@"%@ PV埋点可能重复", data];
                                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:stringTitle message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                                [alertView show];
                            });*/
                            break;
                        }
                    }
                    
                }
            }
        }
        // 不管成功还是失败 给开发提示方便DEBUG
        //        phobosLog(@"%s____数据校验成功", __func__);
        [dataArray addObject:data];
#endif
    } else {
        dataArray = [NSMutableArray arrayWithObject:data];
    }
    [GMCache storeObjectAtDocumentPathWithkey:PhobosCacheKey object:dataArray];
}

/**
 *  @brief 保存数据到缓存层
 *
 *  @param data 数据
 *
 */
- (void)save:(NSDictionary *)data currentAPI:(NSString *)currentAPI
{
    if (_logEnabled) {
        phobosLog([NSString stringWithFormat:@"save dictionary: %@",data]);
    }
    
    NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]];
    if (dataArray) {
        [dataArray addObject:data];
    }else{
        dataArray = [NSMutableArray arrayWithObject:data];
    }
    [GMCache storeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI] object:dataArray];
}
/**
 *  @brief 从缓存中获取数据，并发送
 *
 *  @since 0.0.1
 */
- (void)fetchDataAndSend{
    NSArray *paramsArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
    if (paramsArray.count>0) {
        [self sendArray:paramsArray cleanCacheRightNow:YES];
    }
    // 其他接口的埋点
    for (NSString *newApi in self.APIArray) {
        NSArray *paramsArray = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:newApi]];
        if (paramsArray.count>0) {
            [self sendArray:paramsArray currentAPI:newApi cleanCacheRightNow:YES];
        }
    }
}

/*
    从缓存区获取数据，发给服务器，请求成功的时候，把缓存区的数据删除掉
 */
- (void)sendArray {
    NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey];
    if (_logEnabled) {
        NSData *data = [NSJSONSerialization dataWithJSONObject:dataArray options:NSJSONWritingPrettyPrinted error:nil];
        NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        phobosLog([NSString stringWithFormat:@"array prepare to fly --✈: %@", jsonString]);
    }
    @try {
        NSData *JSON = [PhobosUtil encodeJSON:dataArray];
        NSData *compressedData = [PhobosUtil compressData:JSON];
        if (compressedData) {
            [PhobosUtil sendData:compressedData success:^(NSInteger code) {
                phobosLog(@"✈ ---------- ✈ data arrived Mars");
                [GMCache removeObjectAtDocumentPathWithkey:PhobosTempCacheKey];
            }];
        }
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}

/*
 从缓存区获取数据，发给服务器，请求成功的时候，把缓存区的数据删除掉
 */
- (void)sendArrayWithCurrentAPI:(NSString *)currentAPI {
    NSString *PhobosTempCacheKeyStr = [PhobosUtil MD5String:[PhobosUtil MD5String:currentAPI]]; // 两次加密作为key值，和缓存的key值作区分
    NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr];
    if (_logEnabled) {
        NSData *data = [NSJSONSerialization dataWithJSONObject:dataArray options:NSJSONWritingPrettyPrinted error:nil];
        NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        phobosLog([NSString stringWithFormat:@"array prepare to fly --✈: %@", jsonString]);
    }
    @try {
        NSData *JSON = [PhobosUtil encodeJSON:dataArray];
        NSData *compressedData = [PhobosUtil compressData:JSON];
        if (compressedData) {
            [PhobosUtil sendData:compressedData currentAPI:currentAPI success:^(NSInteger code) {
                phobosLog(@"✈ ---------- ✈ data arrived Mars");
                [GMCache removeObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr];
            }];
        }
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}
/**
 该方法有改动，现在的逻辑是：当前方法只接受发送的请求，然后把数据转存到另一个缓存区，
 让sendArray方法负责发送，数据一旦转移到缓存区，就把原有的数据干掉。
 @author zhaiguojun 16-10-17 in (null)
 @param array 参数
 @param clean 是否立即清楚缓存
 */
- (void)sendArray:(NSArray *)array cleanCacheRightNow:(BOOL)clean {
    @try {
        //1.获取缓存区的数据，把新数据追加进去

        NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKey];
        if (dataArray) {
            [dataArray addObjectsFromArray:array];
        }else{
            dataArray = [NSMutableArray arrayWithArray:array];
        }
        [GMCache storeObjectAtDocumentPathWithkey:PhobosTempCacheKey object:dataArray];
        //2.把缓存区的数据发送给服务器
        [self sendArray];
        //3.把原有的数据删除
        if (clean) {
            [GMCache removeObjectAtDocumentPathWithkey:PhobosCacheKey];
        }
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}

/**
 上边方法新加了一个API字段
 */
- (void)sendArray:(NSArray *)array currentAPI:(NSString *)currentAPI cleanCacheRightNow:(BOOL)clean {
    @try {
        //1.获取缓存区的数据，把新数据追加进去
        NSString *PhobosTempCacheKeyStr = [PhobosUtil MD5String:[PhobosUtil MD5String:currentAPI]]; // 两次加密作为key值，和缓存的key值作区分
        NSMutableArray *dataArray = [GMCache fetchObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr];
        if (dataArray) {
            [dataArray addObjectsFromArray:array];
        }else{
            dataArray = [NSMutableArray arrayWithArray:array];
        }
        [GMCache storeObjectAtDocumentPathWithkey:PhobosTempCacheKeyStr object:dataArray];
        //2.把缓存区的数据发送给服务器
        [self sendArrayWithCurrentAPI:currentAPI];
        //3.把原有的数据删除
        [GMCache removeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:currentAPI]];
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}
#pragma mark - helpers
- (void)catchNullForEvent:(NSString *)eventId attributes:(NSDictionary *)attributes {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        @try {
            for (NSString *key in attributes.allKeys) {
                if ([attributes[key] isMemberOfClass:[NSNull class]]) {
                    if (self.captureNullExpection) {
                        self.captureNullExpection(eventId, attributes);
                    }
                    break;
                }
            }
        } @catch (NSException *exception) {
            
        }
    });
}


- (void)addNewApi:(NSString *)api {
    for (NSString *item in self.APIArray) {
        if ([api isEqualToString:item]) {
            break;
        }
        [self.APIArray addObject:api];
    }
}

@end
