package com.cocos.game;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.cocos.lib.CocosHelper;
import com.cocos.lib.CocosJavascriptJavaBridge;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


import com.reyun.remote.config.OnRemoteConfigReceivedData;
import com.reyun.remote.config.OnRemoteConfigReceivedGenericsData;
import com.reyun.solar.engine.DeepLinkCallBack;
import com.reyun.solar.engine.DelayDeepLinkCallback;
import com.reyun.solar.engine.OnAttributionListener;
import com.reyun.solar.engine.SeSdkSource;
import com.reyun.solar.engine.SolarEngineManager;
import com.reyun.solar.engine.SolarEngineConfig;
import com.reyun.solar.engine.OnInitializationCallback;
import com.reyun.solar.engine.config.CustomDomain;
import com.reyun.solar.engine.config.RemoteConfig;
import com.reyun.solar.engine.infos.DeeplinkInfo;
import com.reyun.solar.engine.infos.PresetEventType;
import com.reyun.solar.engine.infos.SEAdClickEventModel;
import com.reyun.solar.engine.infos.SEAdImpEventModel;
import com.reyun.solar.engine.infos.SEAppRegisterFirstEventModel;
import com.reyun.solar.engine.infos.SEAttrEventModel;
import com.reyun.solar.engine.infos.SECustomEventModel;
import com.reyun.solar.engine.infos.SECustomFirstEventModel;
import com.reyun.solar.engine.infos.SELoginEventModel;
import com.reyun.solar.engine.infos.SEOrderEventModel;
import com.reyun.solar.engine.infos.SEPurchaseEventModel;
import com.reyun.solar.engine.infos.SERegisterEventModel;
import com.reyun.solar.engine.tracker.SEUserDeleteType;

import com.reyun.remote.config.RemoteConfigManager;

public class SECocosCreatorProxyApi {


    private static final String TAG = "Cocos.SolarEngineSDK";

    public static void hello (String msg) {
        System.out.println (msg);
    }

    public static void preInitSDK (String appkey) {
        Context context = getCocosContext();
        SolarEngineManager.getInstance().preInit(context, appkey);

    }
    public static void initSDKWithConfig (String appkey, String options) {
        Log.e(TAG,"initSDK.......");

        Log.e(TAG,options);

        if (options == null) {
            return;
        }

        if (appkey == null) {
            return;
        }

        try {
            Context context = getCocosContext();
            JSONObject configObject = stringToJSONObject(options);
            String seAppkey = appkey;
            SolarEngineConfig.Builder builder = new SolarEngineConfig.Builder();

            String subLibVersion = "";
            if (configObject.has("sub_lib_version")) {
                subLibVersion = (String) configObject.optString("sub_lib_version");
            }

            if (configObject.has("enableDelayDeeplink")) {
                boolean enableDelayDeeplink = (boolean) configObject.optBoolean("enableDelayDeeplink");
                builder.enableDelayDeeplink(enableDelayDeeplink);
            }

            if (configObject.has("logEnabled")) {
                boolean logEnabled = (boolean) configObject.optBoolean("logEnabled");
                if (logEnabled) {
                    builder.logEnabled();
                }
            }
            if (configObject.has("isGDPRArea")) {
                boolean isGDPRArea = (boolean) configObject.optBoolean("isGDPRArea");
                if (isGDPRArea) {
                    builder.isGDPRArea(isGDPRArea);
                }
            }
            if (configObject.has("isCoppaEnabled")) {
                boolean isCoppaEnabled = (boolean) configObject.optBoolean("isCoppaEnabled");
                builder.setCoppaEnabled(isCoppaEnabled);
            }
            if (configObject.has("isKidsAppEnabled")) {
                boolean isKidsAppEnabled = (boolean) configObject.optBoolean("isKidsAppEnabled");
                builder.setKidsAppEnabled(isKidsAppEnabled);
            }

            if (configObject.has("adPersonalizationEnabled")) {
                boolean adPersonalizationEnabled = (boolean) configObject.optBoolean("adPersonalizationEnabled");
                builder.adPersonalizationEnabled(adPersonalizationEnabled);
            }
            if (configObject.has("adUserDataEnabled")) {
                boolean adUserDataEnabled = (boolean) configObject.optBoolean("adUserDataEnabled");
                builder.adUserDataEnabled(adUserDataEnabled);
            }
            if (configObject.has("fbAppID")) {
                String fbAppID = (String) configObject.optString("fbAppID");
                builder.setFbAppID(fbAppID);
            }

            if (configObject.has("customDomain")) {
                JSONObject customDomainJson = (JSONObject) configObject.opt("customDomain");
                if (customDomainJson != null) {
                    CustomDomain customDomain = new CustomDomain();
                    if (customDomainJson.has("enable")) {
                        boolean enable = (boolean) customDomainJson.optBoolean("enable");
                        customDomain.setEnable(enable);
                    }
                    if (customDomainJson.has("receiverDomain")) {
                        String receiverDomain = (String) customDomainJson.optString("receiverDomain");
                        customDomain.setReceiverDomain(receiverDomain);
                    }
                    if (customDomainJson.has("ruleDomain")) {
                        String ruleDomain = (String) customDomainJson.optString("ruleDomain");
                        customDomain.setRuleDomain(ruleDomain);
                    }
                    if (customDomainJson.has("tcpReceiverHost")) {
                        String tcpReceiverHost = (String) customDomainJson.optString("tcpReceiverHost");
                        customDomain.setTcpReceiverHost(tcpReceiverHost);
                    }
                    if (customDomainJson.has("tcpRuleHost")) {
                        String tcpRuleHost = (String) customDomainJson.optString("tcpRuleHost");
                        customDomain.setTcpRuleHost(tcpRuleHost);
                    }
                    if (customDomainJson.has("tcpGatewayHost")) {
                        String tcpGatewayHost = (String) customDomainJson.optString("tcpGatewayHost");
                        customDomain.setTcpGatewayHost(tcpGatewayHost);
                    }
                    builder.withCustomDomain(customDomain);
                }
            }

            if (configObject.has("remoteConfig")) {
                JSONObject remoteConfigJson = (JSONObject) configObject.opt("remoteConfig");
                if (remoteConfigJson != null) {
                    RemoteConfig remoteConfig = new RemoteConfig();
                    if (remoteConfigJson.has("enable")) {
                        boolean enable = (boolean) remoteConfigJson.optBoolean("enable");
                        remoteConfig.setEnable(enable);
                    }
                    if (remoteConfigJson.has("mergeType")) {
                        int mergeType = (int) remoteConfigJson.optInt("mergeType");
                        if (mergeType == 1) {
                            remoteConfig.setMergeType(RemoteConfig.MergeType.WITH_USER);
                        } else {
                            remoteConfig.setMergeType(RemoteConfig.MergeType.WITH_CACHE);
                        }
                    }
                    if (remoteConfigJson.has("customIDProperties")) {
                        JSONObject customIDProperties = remoteConfigJson.optJSONObject("customIDProperties");
                        if (customIDProperties != null) {
                            remoteConfig.setCustomIDProperties(customIDProperties);
                        }
                    }
                    if (remoteConfigJson.has("customIDEventProperties")) {
                        JSONObject customIDEventProperties = remoteConfigJson.optJSONObject("customIDEventProperties");
                        if (customIDEventProperties != null) {
                            remoteConfig.setCustomIDEventProperties(customIDEventProperties);
                        }
                    }
                    if (remoteConfigJson.has("customIDUserProperties")) {
                        JSONObject customIDUserProperties = remoteConfigJson.optJSONObject("customIDUserProperties");
                        if (customIDUserProperties != null) {
                            remoteConfig.setCustomIDUserProperties(customIDUserProperties);
                        }
                    }
                    builder.withRemoteConfig(remoteConfig);
                }
            }
            if (configObject.has("isDebugModel")) {
                boolean isDebugModel = (boolean) configObject.optBoolean("isDebugModel");
                if (isDebugModel) {
                    builder.isDebugModel(true);
                }
            }
            if (configObject.has("isEnable2GReporting")) {
                boolean isEnable2GReporting = (boolean) configObject.optBoolean("isEnable2GReporting");
                builder.enable2GReporting(isEnable2GReporting);
            }
            SolarEngineConfig config = builder.build();
            JSONObject attrResult = new JSONObject();

            config.setOnAttributionListener(new OnAttributionListener() {

                @Override
                public void onAttributionSuccess(JSONObject jsonObject) {
                    try {
                        if (jsonObject != null) {
                            attrResult.put("code", 0);
                            attrResult.put("data", jsonObject);
                        } else {
                            attrResult.put("code", -1);
                        }
                    } catch (JSONException e) {
                        Log.e(TAG,"onAttributionSuccess JSONException : "+e.toString());
                    }
                    String jsonString = attrResult.toString();
                    callJSMethod("attributionCallback", jsonString);
                }

                @Override
                public void onAttributionFail(int i) {
                    try {
                        attrResult.put("code", i);
                    } catch (JSONException e) {
                        Log.e(TAG,"onAttributionFail JSONException : "+e);
                    }
                    String jsonString = attrResult.toString();
                    callJSMethod("attributionCallback", jsonString);
                }
            });
            SeSdkSource seSdkSource = new SeSdkSource();
            seSdkSource.setSubLibVersion(subLibVersion);
            seSdkSource.setSdkType("CocosCreator");
            SolarEngineManager.getInstance().setSeSdkSource(seSdkSource);
            SolarEngineManager.getInstance().initialize(context, seAppkey, config, new OnInitializationCallback() {
                @Override
                public void onInitializationCompleted(int i) {

                    JSONObject jsonObject = new JSONObject();
                    try {
                        jsonObject.put("code", i);
                    } catch (JSONException e) {
                        Log.e(TAG,"onInitializationCompleted JSONException : "+e);
                    }
                    String jsonString = jsonObject.toString();
                    callJSMethod("initCallback", jsonString);
                }
            });

            JSONObject deeplinkResult = new JSONObject();
            SolarEngineManager.getInstance().setDelayDeepLinkCallback(new DelayDeepLinkCallback() {
                @Override
                public void onReceivedSuccess(JSONObject result) {
                    try {
                        if (result != null) {
                            deeplinkResult.put("code", 0);
                            deeplinkResult.put("data", result);
                        } else {
                            deeplinkResult.put("code", -1);
                        }
                    } catch (JSONException e) {
                        Log.e(TAG,"onReceivedSuccess JSONException : "+e);
                    }
                    String jsonString = deeplinkResult.toString();
                    callJSMethod("delayDeeplinkCallback", jsonString);
                }

                @Override
                public void onReceivedFailed(int errorCode) {
                    try {
                        deeplinkResult.put("code", errorCode);
                    } catch (JSONException e) {
                        Log.e(TAG,"onReceivedFailed JSONException : "+e);
                    }
                    String jsonString = deeplinkResult.toString();
                    callJSMethod("delayDeeplinkCallback", jsonString);
                }
            });

            SolarEngineManager.getInstance().setDeepLinkCallback(new DeepLinkCallBack() {

                @Override
                public void onReceived(int i, DeeplinkInfo deeplinkInfo) {

                    JSONObject callBackResult = new JSONObject();
                    JSONObject data = new JSONObject();
                    try {
                        if (deeplinkInfo != null) {
                            data.put("sedpLink", deeplinkInfo.sedpLink);
                            data.put("turlId", deeplinkInfo.turlId);
                            data.put("from", deeplinkInfo.from);
                            data.put("customParams", deeplinkInfo.customParams);
                        }
                    } catch (JSONException e) {
                        Log.e(TAG,"onReceived JSONException : "+e);
                    }

                    try {
                        callBackResult.put("code", i);
                        callBackResult.put("data", data);
                    } catch (JSONException e) {
                        Log.e(TAG,"onReceived JSONException : "+e);
                    }
                    String jsonString = callBackResult.toString();
                    callJSMethod("deeplinkCallback", jsonString);
                }
            });

        } catch (Exception e) {
            Log.e(TAG, "initialize cause exception:" + e);
        }
    }

    public static String getDistinctId() {
        return SolarEngineManager.getInstance().getDistinctId();
    }

    public static void setGaid(String gaid) {
        if (!TextUtils.isEmpty(gaid)) {
            SolarEngineManager.getInstance().setGaid(gaid);
        }
    }

    public static void setChannel(String channel) {
        if (!TextUtils.isEmpty(channel)) {
            SolarEngineManager.getInstance().setChannel(channel);
        }
    }

    public static void setVisitorId (String visitorId) {
        if (!TextUtils.isEmpty(visitorId)) {
            SolarEngineManager.getInstance().setVisitorID(visitorId);
        }
    }
    public static String getVisitorId() {
        return SolarEngineManager.getInstance().getVisitorID();
    }

    public static void login(String accountId) {
        if (!TextUtils.isEmpty(accountId)) {

            SolarEngineManager se = SolarEngineManager.getInstance();

            se.login(accountId);
        }
    }

    public static String getAccountId() {
        return SolarEngineManager.getInstance().getAccountID();
    }

    public static void logout() {
        SolarEngineManager.getInstance().logout();
    }

    public static void eventStart(String eventName) {
        if (!TextUtils.isEmpty(eventName)) {
            SolarEngineManager.getInstance().eventStart(eventName);
        } else {
            Log.e(TAG, "eventStart failed, eventName is empty!");
        }
    }

    public static void eventFinish(String eventName, String options) {

        if (TextUtils.isEmpty(eventName)) {
            Log.e(TAG, "eventFinish failed, eventName is empty!");
            return;
        }

        JSONObject properties = null;
        if (options != null) {
            properties = stringToJSONObject(options);
        }
        SolarEngineManager.getInstance().eventFinish(eventName, properties);
    }

    public static void trackFirstEvent(String firstCheckId, String eventName, String options) {

        if (TextUtils.isEmpty(eventName)) {
            Log.e(TAG, "eventFinish failed, eventName is empty!");
            return;
        }

        JSONObject properties = null;
        if (options != null) {
            properties = stringToJSONObject(options);
        }

        if (eventName.equals("_appReg")) {
            JSONObject data = stringToJSONObject(options);
            SEAppRegisterFirstEventModel seRegisterEventModel = new SEAppRegisterFirstEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seRegisterEventModel.setCustomProperties(customProperties);
            }
            String registerType = data.optString("registerType");
            if (!TextUtils.isEmpty(registerType)) {
                seRegisterEventModel.setRegType(registerType);
            }
            String registerStatus = data.optString("registerStatus");
            if (!TextUtils.isEmpty(registerStatus)) {
                seRegisterEventModel.setStatus(registerStatus);
            }
            if (!TextUtils.isEmpty(firstCheckId)) {
                seRegisterEventModel.setCheckId(firstCheckId);
            }
            SolarEngineManager.getInstance().trackFirstEvent(seRegisterEventModel);

        } else  {

            if(eventName.charAt(0) == '_') {
                Log.e(TAG, "trackFirstEvent Error:" + "trackFirstEvent api only support _appReg event and custom event.");
            }

            SECustomFirstEventModel seCustomEventModel = new SECustomFirstEventModel();
            if (properties != null) {
                seCustomEventModel.setCustomProperties(properties);
            }
            if (!TextUtils.isEmpty(eventName)) {
                seCustomEventModel.setEventName(eventName);
            }
            if (!TextUtils.isEmpty(firstCheckId)) {
                seCustomEventModel.setCheckId(firstCheckId);
            }
        }
    }

    public static void trackCustom(String options) {

        if (options != null) {
            JSONObject data = stringToJSONObject(options);
            SECustomEventModel seCustomEventModel = new SECustomEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seCustomEventModel.setCustomProperties(customProperties);
            }
            String eventName = data.optString("eventName");
            if (!TextUtils.isEmpty(eventName)) {
                seCustomEventModel.setCustomEventName(eventName);
            }
            JSONObject preAttributes = data.optJSONObject("preAttributes");
            if (preAttributes != null) {
                seCustomEventModel.setPreEventData(preAttributes);
            }
            SolarEngineManager.getInstance().track(seCustomEventModel);
        }
    }

    public static void trackAdImpression(String options) {
        if (options != null) {
            Map<String, Object> eventData = stringToMap(options);

            SEAdImpEventModel seAdImpEventModel = new SEAdImpEventModel();
            JSONObject customJson = (JSONObject) eventData.get("customProperties");
            if (customJson != null) {
                seAdImpEventModel.setCustomProperties(customJson);
            }
            String adPlatform = (String) eventData.get("adPlatform");
            if (!TextUtils.isEmpty(adPlatform)) {
                seAdImpEventModel.setAdNetworkPlatform(adPlatform);
            }
            try {
                int adType = (int) eventData.get("adType");
                seAdImpEventModel.setAdType(adType);
            } catch (Exception e) {
                Log.e(TAG, "setAdType Exception:" + e.toString());
            }
            String adAppId = (String) eventData.get("adAppId");
            if (!TextUtils.isEmpty(adAppId)) {
                seAdImpEventModel.setAdNetworkAppID(adAppId);
            }
            String adId = (String) eventData.get("adId");
            if (!TextUtils.isEmpty(adId)) {
                seAdImpEventModel.setAdNetworkADID(adId);
            }
            String mediationPlatform = (String) eventData.get("mediationPlatform");
            if (!TextUtils.isEmpty(mediationPlatform)) {
                seAdImpEventModel.setMediationPlatform(mediationPlatform);
            }
            try {
                Double adEcpm = (Double) eventData.get("adEcpm");
                seAdImpEventModel.setEcpm(adEcpm);
            } catch (Exception e) {
                Log.e(TAG, "setEcpm Exception:" + e.toString());
            }
            String currencyType = (String) eventData.get("currencyType");
            if (!TextUtils.isEmpty(currencyType)) {
                seAdImpEventModel.setCurrencyType(currencyType);
            }
            try {
                boolean isRendered = (boolean) eventData.get("isRendered");
                seAdImpEventModel.setRenderSuccess(isRendered);
            } catch (Exception e) {
                Log.e(TAG, "setRenderSuccess Exception:" + e.toString());
            }
            SolarEngineManager.getInstance().trackAdImpression(seAdImpEventModel);
        }
    }

    public static void trackPurchase(String options) {
        if (options != null) {
            Map<String, Object> eventData = stringToMap(options);
            SEPurchaseEventModel sePurchaseEventModel = new SEPurchaseEventModel();
            JSONObject customJson = (JSONObject) eventData.get("customProperties");
            if (customJson != null) {
                sePurchaseEventModel.setCustomProperties(customJson);
            }
            String orderId = (String) eventData.get("orderId");
            if (!TextUtils.isEmpty(orderId)) {
                sePurchaseEventModel.setOrderId(orderId);
            }
            try {
                double payAmount = (double) eventData.get("payAmount");
                sePurchaseEventModel.setPayAmount(payAmount);
            } catch (Exception e) {
                Log.e(TAG, "trackPurchase setPayAmount Exception:" + e.toString());
            }
            String currencyType = (String) eventData.get("currencyType");
            if (!TextUtils.isEmpty(currencyType)) {
                sePurchaseEventModel.setCurrencyType(currencyType);
            }
            String payType = (String) eventData.get("payType");
            if (!TextUtils.isEmpty(payType)) {
                sePurchaseEventModel.setPayType(payType);
            }
            String productId = (String) eventData.get("productId");
            if (!TextUtils.isEmpty(productId)) {
                sePurchaseEventModel.setProductId(productId);
            }
            String productName = (String) eventData.get("productName");
            if (!TextUtils.isEmpty(productName)) {
                sePurchaseEventModel.setProductName(productName);
            }
            try {
                int productNum = (int) eventData.get("productNum");
                sePurchaseEventModel.setProductNum(productNum);
            } catch (Exception e) {
                Log.e(TAG, "productNum Exception:" + e.toString());
            }
            try {
                int payStatus = (int) eventData.get("payStatus");
                sePurchaseEventModel.setPayStatus(payStatus);
            } catch (Exception e) {
                Log.e(TAG, "payStatus Exception:" + e.toString());
            }
            String failReason = (String) eventData.get("failReason");
            if (!TextUtils.isEmpty(failReason)) {
                sePurchaseEventModel.setFailReason(failReason);
            }
            SolarEngineManager.getInstance().trackPurchase(sePurchaseEventModel);
        }
    }

    public static void trackAdClick(String options) {
        if (options != null) {
            JSONObject data = stringToJSONObject(options);
            SEAdClickEventModel seAdClickEventModel = new SEAdClickEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seAdClickEventModel.setCustomProperties(customProperties);
            }
            String adPlatform = data.optString("adPlatform");
            if (!TextUtils.isEmpty(adPlatform)) {
                seAdClickEventModel.setAdPlatform(adPlatform);
            }
            int adType = data.optInt("adType");
            seAdClickEventModel.setAdType(adType);
            String adId = data.optString("adId");
            if (!TextUtils.isEmpty(adId)) {
                seAdClickEventModel.setAdNetworkADID(adId);
            }
            String mediationPlatform = data.optString("mediationPlatform");
            if (!TextUtils.isEmpty(mediationPlatform)) {
                seAdClickEventModel.setMediationPlatform(mediationPlatform);
            }
            SolarEngineManager.getInstance().trackAdClick(seAdClickEventModel);
        }
    }

    public static void trackRegister(String options) {
        if (options != null) {
            JSONObject data = stringToJSONObject(options);
            SERegisterEventModel seRegisterEventModel = new SERegisterEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seRegisterEventModel.setCustomProperties(customProperties);
            }
            String registerType = data.optString("registerType");
            if (!TextUtils.isEmpty(registerType)) {
                seRegisterEventModel.setRegType(registerType);
            }
            String registerStatus = data.optString("registerStatus");
            if (!TextUtils.isEmpty(registerStatus)) {
                seRegisterEventModel.setStatus(registerStatus);
            }
            SolarEngineManager.getInstance().trackAppRegister(seRegisterEventModel);
        }
    }

    public static void trackLogin(String options) {
        if (options != null) {
            JSONObject data = stringToJSONObject(options);
            SELoginEventModel seLoginEventModel = new SELoginEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seLoginEventModel.setCustomProperties(customProperties);
            }
            String loginType = data.optString("loginType");
            if (!TextUtils.isEmpty(loginType)) {
                seLoginEventModel.setLoginType(loginType);
            }
            String loginStatus = data.optString("loginStatus");
            if (!TextUtils.isEmpty(loginStatus)) {
                seLoginEventModel.setStatus(loginStatus);
            }
            SolarEngineManager.getInstance().trackAppLogin(seLoginEventModel);
        }
    }

    public static void trackOrder(String options) {
        if (options != null) {
            Map<String, Object> eventData = stringToMap(options);

            SEOrderEventModel seOrderEventModel = new SEOrderEventModel();
            JSONObject customJson = (JSONObject) eventData.get("customProperties");
            if (customJson != null) {
                seOrderEventModel.setCustomProperties(customJson);
            }
            String orderId = (String) eventData.get("orderId");
            if (!TextUtils.isEmpty(orderId)) {
                seOrderEventModel.setOrderId(orderId);
            }
            try {
                double payAmount = (double)eventData.get("payAmount");
                seOrderEventModel.setPayAmount(payAmount);
            } catch (Exception e) {
                Log.e(TAG, "trackOrder setPayAmount Exception:" + e.toString());
            }
            String currencyType = (String) eventData.get("currencyType");
            if (!TextUtils.isEmpty(currencyType)) {
                seOrderEventModel.setCurrencyType(currencyType);
            }
            String payType = (String) eventData.get("payType");
            if (!TextUtils.isEmpty(payType)) {
                seOrderEventModel.setPayType(payType);
            }
            String status = (String) eventData.get("status");
            if (!TextUtils.isEmpty(status)) {
                seOrderEventModel.setStatus(status);
            }
            SolarEngineManager.getInstance().trackOrder(seOrderEventModel);
        }
    }

    public static void trackAppAttr(String options) {
        if (options != null) {
            JSONObject data = stringToJSONObject(options);

            SEAttrEventModel seAttrEventModel = new SEAttrEventModel();
            JSONObject customProperties = data.optJSONObject("customProperties");
            if (customProperties != null) {
                seAttrEventModel.setCustomProperties(customProperties);
            }
            String adNetwork = data.optString("adNetwork");
            if (!TextUtils.isEmpty(adNetwork)) {
                seAttrEventModel.setAdNetwork(adNetwork);
            }
            String subChannel = data.optString("subChannel");
            if (!TextUtils.isEmpty(subChannel)) {
                seAttrEventModel.setSubChannel(subChannel);
            }
            String adAccountId = data.optString("adAccountId");
            if (!TextUtils.isEmpty(adAccountId)) {
                seAttrEventModel.setAdAccountId(adAccountId);
            }
            String adAccountName = data.optString("adAccountName");
            if (!TextUtils.isEmpty(adAccountName)) {
                seAttrEventModel.setAdAccountName(adAccountName);
            }
            String adCampaignId = data.optString("adCampaignId");
            if (!TextUtils.isEmpty(adCampaignId)) {
                seAttrEventModel.setAdCampaignId(adCampaignId);
            }
            String adCampaignName = data.optString("adCampaignName");
            if (!TextUtils.isEmpty(adCampaignName)) {
                seAttrEventModel.setAdCampaignName(adCampaignName);
            }
            String adOfferId = data.optString("adOfferId");
            if (!TextUtils.isEmpty(adOfferId)) {
                seAttrEventModel.setAdOfferId(adOfferId);
            }
            String adOfferName = data.optString("adOfferName");
            if (!TextUtils.isEmpty(adOfferName)) {
                seAttrEventModel.setAdOfferName(adOfferName);
            }
            String adCreativeId = data.optString("adCreativeId");
            if (!TextUtils.isEmpty(adCreativeId)) {
                seAttrEventModel.setAdCreativeId(adCreativeId);
            }
            String adCreativeName = data.optString("adCreativeName");
            if (!TextUtils.isEmpty(adCreativeName)) {
                seAttrEventModel.setAdCreativeName(adCreativeName);
            }
            String attributionPlatform = data.optString("attributionPlatform");
            if (!TextUtils.isEmpty(attributionPlatform)) {
                seAttrEventModel.setAttributionPlatform(attributionPlatform);
            }
            SolarEngineManager.getInstance().trackAttr(seAttrEventModel);
        }
    }

    public static void userInit(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            SolarEngineManager.getInstance().userInit(properties);
        } else {
            Log.e(TAG, "userInit failed, properties is null!");
        }
    }

    public static void userUpdate(String options) {

        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            SolarEngineManager.getInstance().userUpdate(properties);
        } else {
            Log.e(TAG, "userUpdate failed, properties is null!");
        }
    }

    public static void userAdd(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            SolarEngineManager.getInstance().userAdd(properties);
        } else {
            Log.e(TAG, "userAdd failed, properties is null!");
        }
    }

    public static void userAppend(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            SolarEngineManager.getInstance().userAppend(properties);
        } else {
            Log.e(TAG, "userAppend failed, properties is null!");
        }
    }

    public static void userUnset(String options) {
        if (options != null) {
            try {
                ArrayList<String> stringList = new ArrayList<>();
                JSONArray keys = new JSONArray(options);
                for (int i = 0; i < keys.length(); i++) {
                    stringList.add(keys.getString(i));
                }
                if (stringList.size() > 0) {
                    String[] stringArray = stringList.toArray(new String[0]);
                    SolarEngineManager.getInstance().userUnset(stringArray);
                }
            } catch (JSONException e) {
                Log.e(TAG,"userUnset JSONException : "+e);
            }
        } else {
            Log.e(TAG, "userUnset failed, keys is invalid!");
        }
    }

    public static void userDelete(String deleteType) {
        if (!TextUtils.isEmpty(deleteType)) {
            switch (deleteType) {
                case "byAccountId":
                    SolarEngineManager.getInstance().userDelete(SEUserDeleteType.DELETE_BY_ACCOUNTID);
                    break;
                case "byVisitorId":
                    SolarEngineManager.getInstance().userDelete(SEUserDeleteType.DELETE_BY_VISITORID);
                    break;
                default:
                    Log.e(TAG, "userDelete failed,deleteType is not support! deleteType:"+deleteType);
                    break;
            }
        } else {
            Log.e(TAG, "userDelete failed, deleteType is empty!");
        }
    }

    public static void setSuperProperties(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            Iterator <String> sIterator = properties.keys();
            while (sIterator.hasNext()) {
                try {
                    String key = sIterator.next();
                    Object value = properties.get(key);
                    doProperties(getCocosContext(), key, value);
                } catch (JSONException e) {
                    Log.e(TAG,"setSuperProperties JSONException : "+e);
                }
            }
        } else {
            Log.e(TAG, "setSuperProperties failed, superProperties is null!");
        }
    }
    private static void doProperties(Context context, String key, Object value) {
        if (TextUtils.isEmpty(key)) {
            return;
        }
        if (null == value) {
            return;
        }
        if (value instanceof Integer) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (Integer) value);
        }
        if (value instanceof Float) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (Float) value);
        }
        if (value instanceof Long) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (Long) value);
        }
        if (value instanceof Double) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (Double) value);
        }
        if (value instanceof Boolean) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (Boolean) value);
        }
        if (value instanceof String) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (String) value);
        }
        if (value instanceof JSONArray) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (JSONArray) value);
        }
        if (value instanceof JSONObject) {
            SolarEngineManager.getInstance().setSuperProperties(context, key, (JSONObject) value);
        }
    }

    public static void unsetSuperProperty(String key) {
        if (!TextUtils.isEmpty(key)) {
            SolarEngineManager.getInstance().unsetSuperProperty(getCocosContext(), key);
        } else {
            Log.e(TAG, "unsetSuperProperty failed, key is empty!");
        }
    }

    public static void clearSuperProperties() {
        SolarEngineManager.getInstance().clearSuperProperties(getCocosContext());
    }

    public static void setPresetEventProperties(String presetEventType, String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            int type = Integer.parseInt(presetEventType);
            switch (type) {
                case 0:
                    SolarEngineManager.getInstance().setPresetEventProperties(PresetEventType.AppInstall, properties);
                    break;
                case 1:
                    SolarEngineManager.getInstance().setPresetEventProperties(PresetEventType.AppStart, properties);
                    break;
                case 2:
                    SolarEngineManager.getInstance().setPresetEventProperties(PresetEventType.AppEnd, properties);
                    break;
                case 3:
                    SolarEngineManager.getInstance().setPresetEventProperties(PresetEventType.All, properties);
                    break;
                default:
                    Log.e(TAG, "setPresetEventProperties failed,presetEventType is not support! eventType:"+presetEventType);
                    break;
            }
        } else {
            Log.e(TAG, "setPresetEventProperties failed, presetEventProperties is null!");
        }
    }

    public static void setGDPRArea(String isGDPRArea) {
        Boolean result = Boolean.getBoolean(isGDPRArea);
        SolarEngineManager.getInstance().setGDPRArea(result);
    }

    public static String getAttribution() {
        JSONObject jsonResult = SolarEngineManager.getInstance().getAttribution();
        if (jsonResult == null) {
            return "{}";
        }
        return jsonResult.toString();
    }

    public static String getPresetProperties() {
        JSONObject jsonResult = SolarEngineManager.getInstance().getPresetProperties();
        return jsonResult.toString();
    }

    public static void reportEventImmediately() {
        SolarEngineManager.getInstance().reportEventImmediately();
    }

    public static void setDefaultConfig(String options) {
        if (options != null) {
            try {
                JSONArray defaultConfig = new JSONArray(options);
                RemoteConfigManager.getInstance().setRemoteDefaultConfig(defaultConfig);
            } catch (JSONException e) {
                Log.e(TAG,"setDefaultConfig JSONException : "+e);
            }
        } else {
            Log.e(TAG, "setDefaultConfig failed, defaultConfig is invalid!");
        }
    }

    public static String setRemoteConfigEventProperties(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            RemoteConfigManager.getInstance().setRemoteConfigEventProperties(properties);
        } else {
            Log.e(TAG, "setRemoteConfigEventProperties failed, properties is null!");
        }
        return "{}";
    }

    public static void setRemoteConfigUserProperties(String options) {
        if (options != null) {
            JSONObject properties = stringToJSONObject(options);
            RemoteConfigManager.getInstance().setRemoteConfigUserProperties(properties);
        } else {
            Log.e(TAG, "setRemoteConfigUserProperties failed, properties is null!");
        }
    }

    public static String fastFetchRemoteConfigWithKey(String key) {
        if (!TextUtils.isEmpty(key)) {
            Object obj = RemoteConfigManager.getInstance().fastFetchRemoteConfig(key);
            JSONObject result = new JSONObject();
            try {
                if (obj != null) {
                    result.put("data",obj);
                }
            } catch (JSONException e) {
                Log.e(TAG,"fastFetchRemoteConfigWithKey JSONException : "+e);
            }
            return result.toString();
        } else {
            Log.e(TAG, "fastFetchRemoteConfigWithKey failed, key is empty!");
        }
        return "{}";
    }

    public static String fastFetchRemoteConfig() {
        JSONObject object = RemoteConfigManager.getInstance().fastFetchRemoteConfig();

        if (object == null) {
            return "{}";
        }

        return object.toString();
    }

    public static void asyncFetchRemoteConfigWithKey(String key) {

        if (!TextUtils.isEmpty(key) ) {

            RemoteConfigManager.getInstance().asyncFetchRemoteConfig(key, new OnRemoteConfigReceivedData() {
                @Override
                public void onResult(Object o) {

                    JSONObject result = new JSONObject();
                    try {
                        if (o != null) {
                            result.put("data",o);
                        }
                    } catch (JSONException e) {
                        Log.e(TAG,"asyncFetchRemoteConfigWithKey JSONException : "+e);
                    }

                    callJSMethod("asyncFetchRemoteConfigWithKeyCallback",result.toString());
                }
            });
        }
    }

    public static void asyncFetchRemoteConfig() {

        RemoteConfigManager.getInstance().asyncFetchRemoteConfig(new OnRemoteConfigReceivedGenericsData<JSONObject>() {
            @Override
            public void onResult(JSONObject jsonObject) {

                if (jsonObject != null) {
                    callJSMethod("asyncFetchRemoteConfigCallback", jsonObject.toString());
                } else {
                    callJSMethod("asyncFetchRemoteConfigCallback", "{}");
                }
            }
        });
    }


    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static Context getCocosContext() {
        Class<?> sdkWrapper = null;
        Class<?> cocos2dxActivity = null;
        try {
            sdkWrapper = Class.forName("com.cocos.service.SDKWrapper");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (sdkWrapper == null) {
            try {
                cocos2dxActivity = Class.forName("org.cocos2dx.lib.Cocos2dxActivity");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            if (cocos2dxActivity == null) {
                return null;
            } else {
                try {
                    Method methodGetContext = cocos2dxActivity.getMethod("getContext");
                    return (Context) methodGetContext.invoke(null);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        } else {
            try {
                Method methodShared = sdkWrapper.getMethod("shared");
                Object instance = methodShared.invoke(null);
                if (instance != null) {
                    Method methodGetActivity = sdkWrapper.getMethod("getActivity");
                    return (Activity) methodGetActivity.invoke(instance);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    private static void callJSMethod (String method, String msg) {

        CocosHelper.runOnGameThread(new Runnable() {
            @Override
            public void run() {
                String evalString = "window.__se__" + method + "('" + msg + "')";
                CocosJavascriptJavaBridge.evalString(evalString);
            }
        });

    }

    private static JSONObject stringToJSONObject (String str) {
        if (str != null && !str.isEmpty()) {
            try {
                return new JSONObject(str);
            }
            catch (JSONException e) {
                e.printStackTrace();
                return new JSONObject();
            }
        }
        else  {
            return new JSONObject();
        }
    }

    private static Map<String, Object> stringToMap (String str) {
        Map<String, Object> map = new HashMap<>();
        JSONObject object = stringToJSONObject(str);
        Iterator <String> sIterator = object.keys();
        while (sIterator.hasNext()) {
            try {
                String key = sIterator.next();
                Object value = object.get(key);
                map.put(key,value);
            } catch (JSONException e) {
                Log.e(TAG,"stringToMap JSONException : "+e);
            }
        }
        return map;
    }
}
