//
//  SECocosCreatorProxyApi.m
//

#import "SECocosCreatorProxyApi.h"
#import <SolarEngineSDK/SolarEngineSDK.h>
#import <SESDKRemoteConfig/SESDKRemoteConfig.h>

#if  __has_include(<SolarEngineSDK/SESDKForCN.h>)
    #import <SolarEngineSDK/SESDKForCN.h>
#endif

#if __has_include("cocos/bindings/jswrapper/SeApi.h")
#include "cocos/bindings/jswrapper/SeApi.h"
#endif
#if __has_include("cocos/scripting/js-bindings/jswrapper/SeApi.h")
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#endif
using namespace std;

#define IsNullOrEmpty(s) (s == nil || s.length == 0) ? YES : NO



NSString * const SEAppIAPEventProductID                        = @"productId";
NSString * const SEAppIAPEventProductName                      = @"productName";
NSString * const SEAppIAPEventProductCount                     = @"productNum";
NSString * const SEAppIAPEventOrderID                          = @"orderId";
NSString * const SEAppIAPEventCurrency                         = @"currencyType";
NSString * const SEAppIAPEventPaystatus                        = @"payStatus";
NSString * const SEAppIAPEventPayType                          = @"payType";
NSString * const SEAppIAPEventProductPayAmount                 = @"payAmount";
NSString * const SEAppIAPEventFailReason                       = @"failReason";


NSString * const SEAppIAPEventPayTypeAlipay                    = @"alipay";
NSString * const SEAppIAPEventPayTypeWeixin                    = @"weixin";
NSString * const SEAppIAPEventPayTypeApplePay                  = @"applepay";
NSString * const SEAppIAPEventPayTypePaypal                    = @"paypal";


NSString * const SEAppAdImpressionPropertyAdPlatform           = @"adPlatform";
NSString * const SEAppAdImpressionPropertyAppID                = @"adAppId";
NSString * const SEAppAdImpressionPropertyPlacementID          = @"adId";
NSString * const SEAppAdImpressionPropertyAdType               = @"adType";
NSString * const SEAppAdImpressionPropertyEcpm                 = @"adEcpm";
NSString * const SEAppAdImpressionPropertyCurrency             = @"currencyType";
NSString * const SEAppAdImpressionPropertyMediationPlatform    = @"mediationPlatform";
NSString * const SEAppAdImpressionPropertyRendered             = @"isRendered";


//NSString * const SEAppAppAttrPropertyIsAttr                    = @"_is_attr
NSString * const SEAppAppAttrPropertyAdNetwork                 = @"adNetwork";
NSString * const SEAppAppAttrPropertySubChannel                = @"subChannel";
NSString * const SEAppAppAttrPropertyAdAccountID               = @"adAccountId";
NSString * const SEAppAppAttrPropertyAdAccountName             = @"adAccountName";
NSString * const SEAppAppAttrPropertyAdCampaignID              = @"adCampaignId";
NSString * const SEAppAppAttrPropertyAdCampaignName            = @"adCampaignName";
NSString * const SEAppAppAttrPropertyAdOfferID                 = @"adOfferId";
NSString * const SEAppAppAttrPropertyAdOfferName               = @"adOfferName";
NSString * const SEAppAppAttrPropertyAdCreativeID              = @"adCreativeId";
NSString * const SEAppAppAttrPropertyAdCreativeName            = @"adCreativeName";
NSString * const SEAppAppAttrPropertyAttributionPlatform       = @"attributionPlatform";


NSString * const SEAppRegisterPropertyType                     = @"registerType";
NSString * const SEAppRegisterPropertyStatus                   = @"registerStatus";


NSString * const SEAppLoginPropertyType                        = @"loginType";
NSString * const SEAppLoginPropertyStatus                      = @"loginStatus";


NSString * const SEAppOrderPropertyID                          = @"orderId";
NSString * const SEAppOrderPropertyPayAmount                   = @"payAmount";
NSString * const SEAppOrderPropertyCurrencyType                = @"currencyType";
NSString * const SEAppOrderPropertyPayType                     = @"payType";
NSString * const SEAppOrderPropertyStatus                      = @"status";

NSString * const SEAppKeyCustomProperties                      = @"customProperties";
NSString * const SEAppKeyCustomEventName                       = @"_customEventName";


@interface SEWrapperManager : NSObject

@property (nonatomic,copy)NSString *sub_lib_version;
@property (nonatomic,copy)NSString *sdk_type;

+ (SEWrapperManager *)sharedInstance;

@end
@implementation SEWrapperManager

+ (SEWrapperManager *)sharedInstance {
    static SEWrapperManager * instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _sdk_type = @"CocosCreator";
    }
    return self;
}

@end

@interface NSString (JSON)
- (NSDictionary *)jsonDictionary;
@end
@implementation NSString (JSON)
- (NSDictionary *)jsonDictionary {
    if (self == nil) {
        return @{};
    } else {
        NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
        if (error == nil) {
            return json;
        } else {
            #ifdef DEBUG
            NSLog(@"Json parse error：%@, Json=%@", error.description, self);
            #endif
            return @{};
        }
    }
}
@end

@interface NSDictionary (SafeMode)
- (id)smValueForKey:(NSString *)key;
- (NSString *)toJsonString;

@end
@implementation NSDictionary (SafeMode)
- (id)smValueForKey:(NSString *)key {
    if (key!=nil) {
        return [self valueForKey:key];
    } else {
        return nil;
    }
}

- (NSString *)toJsonString {
    @try {
        NSData *data = [NSJSONSerialization dataWithJSONObject:self options:0 error:0];
        NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        return  string;
    } @catch (NSException *exception) {
        
    }
    return @"{}";

}

@end

@implementation SECocosCreatorProxyApi

+ (void)preInitSDK:(NSString *)appkey {
    [[SolarEngineSDK sharedInstance] preInitWithAppKey:appkey];
}

+ (void)initSDK:(NSString *)appkey withConfig:(NSString *)config {

    NSLog(@"SolarEngineSDK initSDK = %@",config);
    NSDictionary *appConfig = config.jsonDictionary;

    [SEWrapperManager sharedInstance].sub_lib_version = [appConfig smValueForKey:@"sub_lib_version"];

    SEConfig *seConfig = [[SEConfig alloc] init];

    seConfig.isDebugModel         = [appConfig[@"isDebugModel"] boolValue];
    seConfig.logEnabled           = [appConfig[@"logEnabled"] boolValue];
    seConfig.setCoppaEnabled      = [appConfig[@"isCoppaEnabled"] boolValue];
    seConfig.setKidsAppEnabled    = [appConfig[@"isKidsAppEnabled"] boolValue];
    seConfig.enableDelayDeeplink  = [appConfig[@"enableDelayDeeplink"] boolValue];
    seConfig.enable2GReporting    = [appConfig[@"isEnable2GReporting"] boolValue];
    seConfig.isGDPRArea           = [appConfig[@"isGDPRArea"] boolValue];

    seConfig.attAuthorizationWaitingInterval = [appConfig[@"attAuthorizationWaitingInterval"] intValue];

#if  __has_include(<SolarEngineSDK/SESDKForCN.h>)
        if (appConfig[@"caid"]) {
            seConfig.caid                 = appConfig[@"caid"];
        }
#endif
    
    NSDictionary *remoteConfig = appConfig[@"remoteConfig"];
    if (remoteConfig && ![remoteConfig isKindOfClass:NSDictionary.class]) {
        NSLog(@"[SESDKCocos error:] startWithAppKey, remoteConfig error :%@",remoteConfig);
    }

    if ([remoteConfig isKindOfClass:NSDictionary.class]) {
     
        SERemoteConfig *rcConfig = [[SERemoteConfig alloc] init];
        rcConfig.enable          = [remoteConfig[@"enable"] boolValue];
        rcConfig.logEnabled      = [remoteConfig[@"logEnabled"] boolValue];
        int mergeType            = [remoteConfig[@"mergeType"] intValue];
        
        if (mergeType == 1) {
            rcConfig.mergeType = SERCMergeTypeUser;
        } else {
            rcConfig.mergeType = SERCMergeTypeDefault;
        }
        
        NSDictionary *customIDProperties       = remoteConfig[@"customIDProperties"];
        NSDictionary *customIDEventProperties  = remoteConfig[@"customIDEventProperties"];
        NSDictionary *customIDUserProperties   = remoteConfig[@"customIDUserProperties"];
        
        if ([customIDProperties isKindOfClass:NSDictionary.class]) {
            rcConfig.customIDProperties = customIDProperties;
        }
        if ([customIDEventProperties isKindOfClass:NSDictionary.class]) {
            rcConfig.customIDEventProperties = customIDEventProperties;
        }
        if ([customIDUserProperties isKindOfClass:NSDictionary.class]) {
            rcConfig.customIDUserProperties = customIDUserProperties;
        }
        seConfig.remoteConfig = rcConfig;
    }
    
    NSDictionary *customDomainDict = appConfig[@"customDomain"];
    if (customDomainDict && ![customDomainDict isKindOfClass:NSDictionary.class]) {
        NSLog(@"[SESDKCocos error:] startWithAppKey, customDomain error :%@",customDomainDict);
    }

    if ([customDomainDict isKindOfClass:NSDictionary.class]) {
     
        SECustomDomain *customDomain    = [[SECustomDomain alloc] init];
        customDomain.enable             = [customDomainDict[@"enable"] boolValue];
        
        NSString *receiverDomain        = customDomainDict[@"receiverDomain"];
        NSString *ruleDomain            = customDomainDict[@"ruleDomain"];
        NSString *tcpReceiverHost       = customDomainDict[@"tcpReceiverHost"];
        NSString *tcpRuleHost           = customDomainDict[@"tcpRuleHost"];
        NSString *tcpGatewayHost        = customDomainDict[@"tcpGatewayHost"];

        if ([receiverDomain isKindOfClass:NSString.class]) {
            customDomain.receiverDomain = receiverDomain;
        }
        if ([ruleDomain isKindOfClass:NSString.class]) {
            customDomain.ruleDomain = ruleDomain;
        }
        if ([tcpReceiverHost isKindOfClass:NSString.class]) {
            customDomain.receiverTcpHost = tcpReceiverHost;
        }
        if ([tcpRuleHost isKindOfClass:NSString.class]) {
            customDomain.ruleTcpHost = tcpRuleHost;
        }
        if ([tcpGatewayHost isKindOfClass:NSString.class]) {
            customDomain.gatewayTcpHost = tcpGatewayHost;
        }
        seConfig.customDomain = customDomain;
    }
    
    
    [[SolarEngineSDK sharedInstance] setInitCompletedCallback:^(int code) {
     
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[SolarEngineSDK sharedInstance] reportEventImmediately];
        });
        
        NSDictionary *dict = @{@"code":@(code)};
        NSString *msg = [dict toJsonString];
        [SECocosCreatorProxyApi ocCallJSMethod:@"initCallback" msg:msg];
    }];
    
    [[SolarEngineSDK sharedInstance] setAttributionCallback:^(int code, NSDictionary * _Nullable attributionData) {
        
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setObject:@(code) forKey:@"code"];
        if (attributionData) {
            [dict setObject:attributionData forKey:@"data"];
        }
        NSString *msg = [dict toJsonString];
        [SECocosCreatorProxyApi ocCallJSMethod:@"attributionCallback" msg:msg];
    }];
    
    [[SolarEngineSDK sharedInstance] setDelayDeeplinkDeepLinkCallbackWithSuccess:^(SEDelayDeeplinkInfo * _Nullable deeplinkInfo) {
        
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        
        if (deeplinkInfo) {
            [dict setObject:@(0) forKey:@"code"];
            NSMutableDictionary *deeplinkData = [NSMutableDictionary dictionary];
            if (deeplinkInfo.sedpUrlscheme) {
                [deeplinkData setObject:deeplinkInfo.sedpUrlscheme forKey:@"sedpUrlscheme"];
            }
            if (deeplinkInfo.sedpLink) {
                [deeplinkData setObject:deeplinkInfo.sedpLink forKey:@"sedpLink"];
            }
            if (deeplinkInfo.turlId) {
                [deeplinkData setObject:deeplinkInfo.turlId forKey:@"turlId"];
            }
            [dict setObject:deeplinkData forKey:@"data"];
        } else {
            [dict setObject:@(-1) forKey:@"code"];
            //ssss
        }
        NSString *msg = [dict toJsonString];
        [SECocosCreatorProxyApi ocCallJSMethod:@"delayDeeplinkCallback" msg:msg];
        
    } fail:^(NSError * _Nullable error) {
        
        NSDictionary *dict = @{@"code":@(error.code)};
        NSString *msg = [dict toJsonString];
        [SECocosCreatorProxyApi ocCallJSMethod:@"delayDeeplinkCallback" msg:msg];
    }];
    

    [[SolarEngineSDK sharedInstance] setDeepLinkCallback:^(int code, SEDeeplinkInfo * _Nullable deeplinkInfo) {
               
        NSMutableDictionary *deeplinkData = [NSMutableDictionary dictionary];
        if (code == 0){
            if (deeplinkInfo.from) {
                [deeplinkData setObject:deeplinkInfo.from forKey:@"from"];
            }
            if (deeplinkInfo.sedpLink) {
                [deeplinkData setObject:deeplinkInfo.sedpLink forKey:@"sedpLink"];
            }
            if (deeplinkInfo.turlId) {
                [deeplinkData setObject:deeplinkInfo.turlId forKey:@"turlId"];
            }
            if (deeplinkInfo.customParams) {
                [deeplinkData setObject:deeplinkInfo.customParams forKey:@"customParams"];
            }
        }

        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setObject:deeplinkData forKey:@"data"];
        [dict setObject:[NSNumber numberWithInt:code] forKey:@"code"];

        NSString *msg = [dict toJsonString];
        [SECocosCreatorProxyApi ocCallJSMethod:@"deeplinkCallback" msg:msg];

    }];
    

    [[SolarEngineSDK sharedInstance] startWithAppKey:appkey config:seConfig];
}

    


+ (void)setVisitorId:(NSString *)visitorId {
    [[SolarEngineSDK sharedInstance] setVisitorID:visitorId];
}

+ (NSString *)getVisitorId {
    NSString *visitorId = [[SolarEngineSDK sharedInstance] visitorID];
    return visitorId;
}

+ (NSString *)getDistinctId {
    NSString *distinctId = [[SolarEngineSDK sharedInstance] getDistinctId];
    return distinctId;
}

+ (void)login:(NSString *)accountId {
    [[SolarEngineSDK sharedInstance] loginWithAccountID:accountId];
}

+ (NSString *)getAccountId {
    NSString *accountID = [[SolarEngineSDK sharedInstance] accountID];
    return accountID;
}

+ (void)logout {
    [[SolarEngineSDK sharedInstance] logout];
}

+ (void)reportEventImmediately {
    [[SolarEngineSDK sharedInstance] reportEventImmediately];
}

+ (NSString *)getPresetProperties {

    NSDictionary *presetProperties = [[SolarEngineSDK sharedInstance] getPresetProperties];
    return presetProperties.toJsonString;
}

+ (void)setGDPRArea:(NSString *)isGDPRArea {

    [[SolarEngineSDK sharedInstance] setGDPRArea:isGDPRArea.boolValue];
}

+ (void)setPresetEventProperties:(NSString *)eventType withProperties:(NSString *)properties {
    
    if (eventType.intValue == 0) {
        [[SolarEngineSDK sharedInstance] setPresetEvent:SEPresetEventTypeAppInstall withProperties:properties.jsonDictionary];
    } else if (eventType.intValue == 1) {
        [[SolarEngineSDK sharedInstance] setPresetEvent:SEPresetEventTypeAppStart   withProperties:properties.jsonDictionary];
    } else if (eventType.intValue == 2) {
        [[SolarEngineSDK sharedInstance] setPresetEvent:SEPresetEventTypeAppEnd     withProperties:properties.jsonDictionary];
    } else if (eventType.intValue == 3) {
        [[SolarEngineSDK sharedInstance] setPresetEvent:SEPresetEventTypeAppAll     withProperties:properties.jsonDictionary];
    } else {
        NSLog(@"[SESDKCocos error:] setPresetEventProperties eventType fail: %@",eventType);
    }
}

+ (NSString *)getAttribution {
    NSDictionary *attributionData = [[SolarEngineSDK sharedInstance] getAttributionData];
    if (!attributionData) {
        attributionData = @{};
    }
    
    return [attributionData toJsonString];
}

#pragma -mark 公共事件属性

+ (void)setSuperProperties:(NSString *)options {
    [[SolarEngineSDK sharedInstance] setSuperProperties:options.jsonDictionary];
}

+ (void)unsetSuperProperty:(NSString *)key {
    [[SolarEngineSDK sharedInstance] unsetSuperProperty:key];
}

+ (void)clearSuperProperties {
    [[SolarEngineSDK sharedInstance] clearSuperProperties];
}

#pragma -mark 自定义事件

+ (void)trackCustom:(NSString *)jsonString
 {

     NSDictionary *options = jsonString.jsonDictionary;
     
     NSString *eventName = options[@"eventName"];
     NSDictionary *customProperties = options[@"customProperties"];
     NSDictionary *preProperties = options[@"preAttributes"];

    [[SolarEngineSDK sharedInstance] track:eventName withCustomProperties:customProperties withPresetProperties:preProperties];
}

+ (SECustomEventAttribute *)p_buildCustomEventAttribute:(NSDictionary *)options {

    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackCustomEvent arguments not Dictionary !");
        return nil;
    }
    NSDictionary *properties = nil;
    NSString *eventName = nil;
    if ([options isKindOfClass:NSDictionary.class]) {
        properties = options[SEAppKeyCustomProperties];
        eventName  = options[SEAppKeyCustomEventName];
    }
    
    SECustomEventAttribute *attribute = [[SECustomEventAttribute alloc] init];
    attribute.eventName = eventName;
    attribute.customProperties = properties;
    
    return attribute;
}

#pragma -mark 预定义事件

+ (void)trackPurchase:(NSString *)options  {
    
    SEIAPEventAttribute *attribute = [self p_buildIAPEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackIAPWithAttributes:attribute];
}

+ (SEIAPEventAttribute *)p_buildIAPEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackIAPWithAttributes arguments not Dictionary !");
        return nil;
    }
    NSString *productID     = [options objectForKey:SEAppIAPEventProductID];
    NSString *productName   = [options objectForKey:SEAppIAPEventProductName];
    NSString *orderId       = [options objectForKey:SEAppIAPEventOrderID];
    NSString *currencyType  = [options objectForKey:SEAppIAPEventCurrency];
    NSString *payType       = [options objectForKey:SEAppIAPEventPayType];
    NSString *failReason    = [options objectForKey:SEAppIAPEventFailReason];
    NSNumber *payStatus     = [options objectForKey:SEAppIAPEventPaystatus];
    NSNumber *productCount  = [options objectForKey:SEAppIAPEventProductCount];
    NSNumber *payAmount     = [options objectForKey:SEAppIAPEventProductPayAmount];
    NSDictionary *customProperties = [options objectForKey:SEAppKeyCustomProperties];
    
    SEIAPEventAttribute *attribute = [[SEIAPEventAttribute alloc] init];
    attribute.productID         = productID;
    attribute.productName       = productName;
    attribute.orderId           = orderId;
    attribute.currencyType      = currencyType;
    attribute.payType           = payType;
    attribute.payStatus         = (SolarEngineIAPStatus)[payStatus integerValue];
    attribute.failReason        = failReason;
    attribute.payAmount         = [payAmount doubleValue];
    attribute.productCount      = [productCount integerValue];
    attribute.customProperties  = customProperties;
    
    return attribute;
}

+ (void)trackAdImpression:(NSString *)options  {
    
    SEAdImpressionEventAttribute *attribute = [self p_buildAdImpressionEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackAdImpressionWithAttributes:attribute];
    
}

+ (SEAdImpressionEventAttribute *)p_buildAdImpressionEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackAdImpressionWithAttributes arguments not Dictionary !");
        return nil;
    }
    
    NSString *adNetworkPlatform    = [options objectForKey:SEAppAdImpressionPropertyAdPlatform];
    NSString *adNetworkAppID       = [options objectForKey:SEAppAdImpressionPropertyAppID];
    NSString *adNetworkPlacementID = [options objectForKey:SEAppAdImpressionPropertyPlacementID];
    NSString *currency             = [options objectForKey:SEAppAdImpressionPropertyCurrency];
    NSNumber *adType               = [options objectForKey:SEAppAdImpressionPropertyAdType];
    NSNumber *ecpm                 = [options objectForKey:SEAppAdImpressionPropertyEcpm];
    NSString *mediationPlatform    = [options objectForKey:SEAppAdImpressionPropertyMediationPlatform];
    NSNumber *rendered             = [options objectForKey:SEAppAdImpressionPropertyRendered];
    NSDictionary *customProperties = [options objectForKey:SEAppKeyCustomProperties];

    SEAdImpressionEventAttribute *attribute = [[SEAdImpressionEventAttribute alloc] init];
    attribute.adType               = [adType integerValue];
    attribute.adNetworkPlatform    = adNetworkPlatform;
    attribute.adNetworkAppID       = adNetworkAppID;
    attribute.adNetworkPlacementID = adNetworkPlacementID;
    attribute.currency             = currency;
    attribute.mediationPlatform    = mediationPlatform;
    attribute.ecpm                 = [ecpm doubleValue];
    attribute.rendered             = [rendered boolValue];
    attribute.customProperties     = customProperties;
    return attribute;
}

+ (void)trackAdClick:(NSString *)options  {
    
    SEAdClickEventAttribute *attribute = [self p_buildAdClickEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackAdClickWithAttributes:attribute];
}

+ (SEAdClickEventAttribute *)p_buildAdClickEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackAdClickWithAttributes arguments not Dictionary !");
        return nil;
    }

    NSString *adNetworkPlatform    = [options objectForKey:SEAppAdImpressionPropertyAdPlatform];
    NSNumber *adType               = [options objectForKey:SEAppAdImpressionPropertyAdType];
    NSString *adNetworkPlacementID = [options objectForKey:SEAppAdImpressionPropertyPlacementID];
    NSString *mediationPlatform    = [options objectForKey:SEAppAdImpressionPropertyMediationPlatform];
    NSDictionary *customProperties = [options objectForKey:SEAppKeyCustomProperties];
    
    SEAdClickEventAttribute *attribute = [[SEAdClickEventAttribute alloc] init];
    attribute.adType                 = [adType integerValue];
    attribute.adNetworkPlatform      = adNetworkPlatform;
    attribute.adNetworkPlacementID   = adNetworkPlacementID;
    attribute.mediationPlatform      = mediationPlatform;
    attribute.customProperties       = customProperties;
    
    return attribute;
}

+ (void)trackAppAttr:(NSString *)options  {
    
    SEAppAttrEventAttribute *appAttr = [self p_buildAppAttrEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackAppAttrWithAttributes:appAttr];
    
}
+ (SEAppAttrEventAttribute *)p_buildAppAttrEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackAppAttrWithAttributes arguments not Dictionary !");
        return nil;
    }

    NSString *adNetwork            = [options objectForKey:SEAppAppAttrPropertyAdNetwork];
    NSString *subChannel           = [options objectForKey:SEAppAppAttrPropertySubChannel];
    NSString *adAccountID          = [options objectForKey:SEAppAppAttrPropertyAdAccountID];
    NSString *adAccountName        = [options objectForKey:SEAppAppAttrPropertyAdAccountName];
    NSString *adCampaignID         = [options objectForKey:SEAppAppAttrPropertyAdCampaignID];
    NSString *adCampaignName       = [options objectForKey:SEAppAppAttrPropertyAdCampaignName];
    NSString *adOfferID            = [options objectForKey:SEAppAppAttrPropertyAdOfferID];
    NSString *adOfferName          = [options objectForKey:SEAppAppAttrPropertyAdOfferName];
    NSString *adCreativeID         = [options objectForKey:SEAppAppAttrPropertyAdCreativeID];
    NSString *adCreativeName       = [options objectForKey:SEAppAppAttrPropertyAdCreativeName];
    NSString *attributionPlatform  = [options objectForKey:SEAppAppAttrPropertyAttributionPlatform];
    NSDictionary *customProperties = [options objectForKey:SEAppKeyCustomProperties];

    SEAppAttrEventAttribute *appAttr = [[SEAppAttrEventAttribute alloc] init];
    appAttr.adNetwork           = adNetwork;
    appAttr.subChannel          = subChannel;
    appAttr.adAccountID         = adAccountID;
    appAttr.adAccountName       = adAccountName;
    appAttr.adCampaignID        = adCampaignID;
    appAttr.adCampaignName      = adCampaignName;
    appAttr.adOfferID           = adOfferID;
    appAttr.adOfferName         = adOfferName;
    appAttr.adCreativeID        = adCreativeID;
    appAttr.adCreativeName      = adCreativeName;
    appAttr.attributionPlatform = attributionPlatform;
    appAttr.customProperties    = customProperties;
    
    return appAttr;
}

+ (void)trackRegister:(NSString *)options  {
    
    SERegisterEventAttribute *attribute = [self p_buildRegisterEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackRegisterWithAttributes:attribute];
}

+ (SERegisterEventAttribute *)p_buildRegisterEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackRegisterWithAttributes arguments not Dictionary !");
        return nil;
    }

    NSString *type                 = [options objectForKey:SEAppRegisterPropertyType];
    NSString *status               = [options objectForKey:SEAppRegisterPropertyStatus];
    NSDictionary *customProperties = [options objectForKey:SEAppKeyCustomProperties];
    
    SERegisterEventAttribute *attribute = [[SERegisterEventAttribute alloc] init];
    attribute.registerType      = type;
    attribute.registerStatus    = status;
    attribute.customProperties  = customProperties;
    return attribute;
}

+ (void)trackLogin:(NSString *)options  {
    
    SELoginEventAttribute *attribute = [self p_buildLoginEventAttribute:options.jsonDictionary];
    
    [[SolarEngineSDK sharedInstance] trackLoginWithAttributes:attribute];
}

+ (SELoginEventAttribute *)p_buildLoginEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackLoginWithAttributes arguments not Dictionary !");
        return nil;
    }
        
    NSString *type                  = [options objectForKey:SEAppLoginPropertyType];
    NSString *status                = [options objectForKey:SEAppLoginPropertyStatus];
    NSDictionary *customProperties  = [options objectForKey:SEAppKeyCustomProperties];

    SELoginEventAttribute *attribute = [[SELoginEventAttribute alloc] init];
    attribute.loginType         = type;
    attribute.loginStatus       = status;
    attribute.customProperties  = customProperties;
    return attribute;
}

+ (void)trackOrder:(NSString *)options  {

    SEOrderEventAttribute *attribute = [self p_buildOrderEventAttribute:options.jsonDictionary];
    [[SolarEngineSDK sharedInstance] trackOrderWithAttributes:attribute];
    
}

+ (SEOrderEventAttribute *)p_buildOrderEventAttribute:(NSDictionary *)options {
    
    if (![options isKindOfClass:[NSDictionary class]]) {
        NSLog(@"[SESDKCocos error:] trackOrderWithAttributes arguments not Dictionary !");
        return nil;
    }

    NSString *orderID               = [options objectForKey:SEAppOrderPropertyID];
    NSNumber *payAmount             = [options objectForKey:SEAppOrderPropertyPayAmount];
    NSString *currencyType          = [options objectForKey:SEAppOrderPropertyCurrencyType];
    NSString *payType               = [options objectForKey:SEAppOrderPropertyPayType];
    NSString *status                = [options objectForKey:SEAppOrderPropertyStatus];
    NSDictionary *customProperties  = [options objectForKey:SEAppKeyCustomProperties];
    
    SEOrderEventAttribute *attribute = [[SEOrderEventAttribute alloc] init];
    attribute.orderID             = orderID;
    attribute.payAmount           = [payAmount doubleValue];
    attribute.currencyType        = currencyType;
    attribute.payType             = payType;
    attribute.status              = status;
    attribute.customProperties    = customProperties;

    return attribute;
}

+ (void)eventStart:(NSString *)eventName {
    
    [[SolarEngineSDK sharedInstance] eventStart:eventName];
}

+ (void)eventFinish:(NSString *)eventName customProperties:(NSString *)options {

    NSDictionary *customProperties = options.jsonDictionary;
    [[SolarEngineSDK sharedInstance] eventFinish:eventName properties:customProperties];

}

// 首次事件只支持 注册事件 和 自定义事件
+ (void)trackFirstEvent:(NSString *)firstCheckId
              eventName:(NSString *)eventName
             properties:(NSString *)options {
    
    NSLog(@"trackFirstEvent firstCheckId:%@,eventName:%@,options:%@",firstCheckId,eventName,options);
    
    if ([eventName isEqualToString:@"_appReg"]) {
        
        SERegisterEventAttribute *attribute = [self p_buildRegisterEventAttribute:options.jsonDictionary];
        attribute.firstCheckId = firstCheckId;
        [[SolarEngineSDK sharedInstance] trackFirstEvent:attribute];

    } else {
        
        if ([eventName hasPrefix:@"_"]) {
            NSLog(@"[SolarEngine Cocos] Error: trackFirstEvent api only support _appReg event and custom event.");
        }
        
        SECustomEventAttribute *attribute = [self p_buildCustomEventAttribute:options.jsonDictionary];
        attribute.firstCheckId = firstCheckId;
        [[SolarEngineSDK sharedInstance] trackFirstEvent:attribute];
    }
}

#pragma -mark 用户属性参数

+ (void)userInit:(NSString *)options {
    
    NSDictionary *dict = options.jsonDictionary;
    [[SolarEngineSDK sharedInstance] userInit:dict];
    
}

+ (void)userUpdate:(NSString *)options {
        
    NSDictionary *dict = options.jsonDictionary;
    [[SolarEngineSDK sharedInstance] userUpdate:dict];
    
}

+ (void)userAdd:(NSString *)options {
    
    NSDictionary *dict = options.jsonDictionary;
    [[SolarEngineSDK sharedInstance] userAdd:dict];
    
}

+ (void)userUnset:(NSString *)options {
    
    NSArray *list = @[];

    if (options) {
        NSData *data = [options dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
        if (error) {
            return NSLog(@"userUnset error = %@",error);
        } else {
            list = json;
        }
    }
    
    [[SolarEngineSDK sharedInstance] userUnset:list];
    
}

+ (void)userAppend:(NSString *)options {

    NSDictionary *dict = options.jsonDictionary;
    [[SolarEngineSDK sharedInstance] userAppend:dict];
    
}

+ (void)userDelete:(NSString *)type {
    
    if ([type isEqualToString:@"byAccountId"]) {
        [[SolarEngineSDK sharedInstance] userDelete:SEUserDeleteTypeByAccountId];
    } else if ([type isEqualToString:@"byVisitorId"]) {
        [[SolarEngineSDK sharedInstance] userDelete:SEUserDeleteTypeByVisitorId];
    } else {
        NSLog(@"[SESDKCocos error:] userDelete arguments fail : %@",type);
    }
}

+ (void)updatePostbackConversionValue:(NSString *)fineValue {
          
    [[SolarEngineSDK sharedInstance] updatePostbackConversionValue:fineValue.intValue completionHandler:^(NSError * _Nonnull error) {
        
        NSDictionary *dict = @{@"code":@(error.code)};
        NSString *msg = dict.toJsonString;
        [SECocosCreatorProxyApi ocCallJSMethod:@"updatePostbackConversionValueCallback" msg:msg];
        
    }];
}

+ (void)updatePostbackConversionAndCoarseValue:(NSString *)fineValue coarseValue:(NSString *)coarseValue {
    
    [[SolarEngineSDK sharedInstance] updatePostbackConversionValue:fineValue.intValue coarseValue:coarseValue completionHandler:^(NSError * _Nonnull error) {
        
        NSDictionary *dict = @{@"code":@(error.code)};
        NSString *msg = dict.toJsonString;
        [SECocosCreatorProxyApi ocCallJSMethod:@"updatePostbackConversionValueCallback" msg:msg];
        
    }];
}

+ (void)updatePostbackConversionAndCoarseValueAndlockWindow:(NSString *)fineValue coarseValue:(NSString *)coarseValue lockWindow:(NSString *)lockWindow  {
    
    [[SolarEngineSDK sharedInstance] updatePostbackConversionValue:fineValue.intValue coarseValue:coarseValue lockWindow:lockWindow.boolValue completionHandler:^(NSError * _Nonnull error) {
        
        NSDictionary *dict = @{@"code":@(error.code)};
        NSString *msg = dict.toJsonString;
        [SECocosCreatorProxyApi ocCallJSMethod:@"updatePostbackConversionValueCallback" msg:msg];
        
    }];
    
}

+ (void)requestTrackingAuthorization {
        
    [[SolarEngineSDK sharedInstance] requestTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) {
        
        NSDictionary *dict = @{@"code":@(status)};
        NSString *msg = dict.toJsonString;
        [SECocosCreatorProxyApi ocCallJSMethod:@"requestTrackingAuthorizationCallback" msg:msg];
        
    }];
}

#pragma mark -- SESDKRemoteConfig

+ (void)setDefaultConfig:(NSString *)options {

    NSArray *list = nil;
    if (options) {
        NSData *data = [options dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
        if (error != nil) {
            NSLog(@"setDefaultConfig options = %@",options);
            NSLog(@"setDefaultConfig error = %@",error);
        } else {
            list = json;
        }
    }
        
    [[SESDKRemoteConfig sharedInstance] setDefaultConfig:list];
}

+ (void)setRemoteConfigEventProperties:(NSString *)options {
    
    NSDictionary *properties = options.jsonDictionary;
    [[SESDKRemoteConfig sharedInstance] setRemoteConfigEventProperties:properties];
}

+ (void)setRemoteConfigUserProperties:(NSString *)options {
        
    NSDictionary *properties = options.jsonDictionary;
    [[SESDKRemoteConfig sharedInstance] setRemoteConfigUserProperties:properties];
}

+ (NSString *)fastFetchRemoteConfigWithKey:(NSString *)key {
    
    NSDictionary *data = @{};
    id value = [[SESDKRemoteConfig sharedInstance] fastFetchRemoteConfig:[key copy]];
    if (value) {
        data = @{
            @"data":value
        };
    }
    return data.toJsonString;

}

+ (NSString *)fastFetchRemoteConfig {
    NSDictionary *data = [[SESDKRemoteConfig sharedInstance] fastFetchRemoteConfig];
    
    if (data) {
        return data.toJsonString;
    } else {
        return @"{}";
    }
}


+ (void)asyncFetchRemoteConfigWithKey:(NSString *)key {
    
    [[SESDKRemoteConfig sharedInstance] asyncFetchRemoteConfig:[key copy] completionHandler:^(id  _Nonnull data) {
        
        NSDictionary *dict = @{};
        if (data) {
            dict = @{
                @"data":data
            };
        }
        
        NSString *msg = dict.toJsonString;
        [SECocosCreatorProxyApi ocCallJSMethod:@"asyncFetchRemoteConfigWithKeyCallback" msg:msg];
    }];
}

+ (void)asyncFetchRemoteConfig {
   
    [[SESDKRemoteConfig sharedInstance] asyncFetchRemoteConfigWithCompletionHandler:^(NSDictionary * _Nonnull dict) {
        
        NSString *msg = @"{}";
        if (dict) {
            msg = dict.toJsonString;
        }
        
        [SECocosCreatorProxyApi ocCallJSMethod:@"asyncFetchRemoteConfigCallback" msg:msg];

    }];
}


+ (void)ocCallJSMethod:(NSString *)selector msg:(NSString *)message {
    
    if (selector == NULL) {
        NSLog(@"ocCallJSMethod selector is null");
        return;
    }
    
    const char *msg = NULL;
    if (message != NULL) {
        msg = [message UTF8String];
    }
    
    const char *sel = [selector UTF8String];
    [SECocosCreatorProxyApi callJSMethod:sel msg:msg];
}

+ (const char *)callJSMethod:(const char *)selector msg:(const char *)msg {
    std::string s = "window.__se__";
    s += selector;
    s += "('";
    s += msg;
    s += "')";
    
    dispatch_async(dispatch_get_main_queue(), ^{
        se::ScriptEngine::getInstance()->evalString(s.c_str());
    });    
    
}

@end
