package com.seayoo.sdk;

import android.util.Log;

import com.google.gson.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.seayoo.sdk.api.ComboSDK;
import com.seayoo.sdk.api.model.ComboSDKLoginInfo;
import com.seayoo.sdk.api.model.options.AdsOptions;
import com.seayoo.sdk.api.model.options.ComboSDKFeature;
import com.seayoo.sdk.api.model.options.ComboSDKImageShareOptions;
import com.seayoo.sdk.api.model.options.ComboSDKPurchaseOptions;
import com.seayoo.sdk.api.model.options.ComboSDKRoleInfo;
import com.seayoo.sdk.api.model.options.ComboSDKSetupOptions;
import com.seayoo.sdk.api.model.options.ComboSDKShareOptions;
import com.seayoo.sdk.api.model.options.ComboSDKShareScene;
import com.seayoo.sdk.api.model.options.ComboSDKShareTarget;
import com.seayoo.sdk.api.model.options.ComboSDKUpdateGameOptions;
import com.seayoo.sdk.api.model.options.ComboSDKVideoShareOptions;
import com.seayoo.sdk.api.model.options.ComboSDKLinkShareOptions;
import com.seayoo.sdk.api.model.options.CheckAnnouncementsOptions;
import com.seayoo.sdk.api.model.options.OpenAnnouncementsOptions;
import com.seayoo.sdk.api.model.options.ComplainOptions;
import com.seayoo.sdk.api.model.options.PromoPseudoPurchaseOptions;
import com.seayoo.sdk.api.model.options.LanguagePreference;
import com.seayoo.sdk.api.model.options.RedeemGiftCodeOptions;
import com.seayoo.sdk.combo.model.GameUrl;
import com.unity3d.player.UnityPlayer;

import java.lang.reflect.Type;
import java.util.Map;

public class ComboSDKAndroidWrapper {

    public static final String TAG = "ComboSDKAndroidWrapper";

    private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    private static Boolean setupFinished = false;

    private static Boolean loginPended = false;

    public static void Setup(String jsonStr) {
        Log.d(TAG, "<Setup> Received unity message: " + jsonStr);
        ComboSDK.getInstance().setup(UnityPlayer.currentActivity, gson.fromJson(jsonStr, ComboSDKSetupOptions.class), result -> {
            setupFinished = true;
            if (result.isSuccess()) {
                RegisterKickOut();
                //RegisterSwitchAccount();
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Setup> Send message to unity: " + resultStr);
                SendJson("_SetupSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Setup> Send message to unity: " + resultStr);
                SendJson("_SetupFailed", resultStr);
            }
            if (loginPended) {
                loginPended = false;
                Log.d(TAG, "<Setup> Trigger pended login event");
                _Login();
            }
        });
    }
    
    public static void Login() {
        Log.d(TAG, "<Login> Received unity message: null");
        if (!setupFinished) {
            Log.d(TAG, "<Login> Pended, ComboSDK.Setup not finished");
            loginPended = true;
        } else {
            _Login();
        }
    }

    private static void _Login() {
        SetKeepRenderingOnPause();
        ComboSDK.getInstance().login(UnityPlayer.currentActivity, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Login> Send message to unity: " + resultStr);
                SendJson("_LoginSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Login> Send message to unity: " + resultStr);
                SendJson("_LoginFailed", resultStr);
            }
        });
    }

    public static String GetLoginInfo() {
        Log.d(TAG, "<GetLoginInfo> Received unity message: null");
        ComboSDKLoginInfo info = ComboSDK.getInstance().getLoginInfo();
        String resultStr = gson.toJson(info);
        Log.d(TAG, "<GetLoginInfo> Send message to unity: " + resultStr);
        return resultStr;
    }

    public static void Logout() {
        Log.d(TAG, "<Logout> Received unity message: null");
        ComboSDK.getInstance().logout(UnityPlayer.currentActivity, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Logout> Send message to unity: " + resultStr);
                SendJson("_LogoutSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Logout> Send message to unity: " + resultStr);
                SendJson("_LogoutFailed", resultStr);
            }
        });
    }

    public static void Purchase(String jsonStr) {
        Log.d(TAG, "<Purchase> Received unity message: " + jsonStr);
        ComboSDKPurchaseOptions opts = gson.fromJson(jsonStr, ComboSDKPurchaseOptions.class);
        ComboSDK.getInstance().purchase(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Purchase> Send message to unity: " + resultStr);
                SendJson("_PurchaseSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Purchase> Send message to unity: " + resultStr);
                SendJson("_PurchaseFailed", resultStr);
            }
        });
    }

    public static void PreloadAd(String jsonStr) {
        Log.d(TAG, "<PreloadAd> Received unity message: " + jsonStr);
        AdsOptions opts = gson.fromJson(jsonStr, AdsOptions.class);
        ComboSDK.getInstance().preloadAd(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<PreloadAd> Send message to unity: " + resultStr);
                SendJson("_PreloadAdSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<PreloadAd> Send message to unity: " + resultStr);
                SendJson("_PreloadAdFailed", resultStr);
            }
        });
    }

    public static void ShowAd(String jsonStr) {
        Log.d(TAG, "<ShowAd> Received unity message: " + jsonStr);
        AdsOptions opts = gson.fromJson(jsonStr, AdsOptions.class);
        ComboSDK.getInstance().showAd(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<ShowAd> Send message to unity: " + resultStr);
                SendJson("_ShowAdSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<ShowAd> Send message to unity: " + resultStr);
                SendJson("_ShowAdFailed", resultStr);
            }
        });
    }
    
    public static void Share(String type, String jsonStr) {
        Log.d(TAG, "<Share> Received unity message: " + jsonStr);
        String[] legacyKeys = {"Contents"};
        jsonStr = getAdaptedJsonStr(jsonStr, "Text", legacyKeys);
        Log.d(TAG, "<Share> Share adapted json message: " + jsonStr);
        ComboSDKShareOptions opts = null;
        Gson gson = new GsonBuilder()
            .registerTypeAdapter(ComboSDKShareScene.class, new ComboSDKShareSceneDeserializer())
            .registerTypeAdapter(ComboSDKShareTarget.class, new ComboSDKShareTargetDeserializer())
            .create();
        switch (type) {
            case "ImageShareOptions":
                opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), ComboSDKImageShareOptions.class);
                break;
            case "VideoShareOptions":
                opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), ComboSDKVideoShareOptions.class);
                break;
            case "LinkShareOptions":
                opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), ComboSDKLinkShareOptions.class);
                break;
            default:
                opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), ComboSDKImageShareOptions.class);
                Log.e(TAG, "<Share> Unknown share type: " + type + ", fallback to ComboSDKImageShareOptions");
                break;
        }
        ComboSDK.getInstance().share(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Share> Send message to unity: " + resultStr);
                SendJson("_ShareSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Share> Send message to unity: " + resultStr);
                SendJson("_ShareFailed", resultStr);
            }
        });
    }
    
    public static String GetAvailableShareTargets() {
        Log.d(TAG, "<GetAvailableShareTargets> Received unity message: null");
        String result = gson.toJson(ComboSDK.getInstance().getAvailableShareTargets());
        return result;
    }
    
    public static boolean IsFeatureAvailable(int value) {
        Log.d(TAG, "<IsFeatureAvailable> Received unity message: " + value);
        ComboSDKFeature feature;
        switch (value) {
            case 0:
                feature = ComboSDKFeature.UPDATE_GAME;
                break;
            case 1:
                feature = ComboSDKFeature.QUIT;
                break;
            case 2:
                feature = ComboSDKFeature.PRODUCT_QUANTITY;
                break;
            case 3:
                feature = ComboSDKFeature.SEAYOO_ACCOUNT;
                break;
            case 4:
                feature = ComboSDKFeature.CONTACT_SUPPORT;
                break;
            case 5:
                feature = ComboSDKFeature.REPORT_DOUYIN_CUSTOM_EVENT;
                break;
            default:
                return false;
        }
        return ComboSDK.getInstance().isFeatureAvailable(feature);
    }

    public static void UpdateGame(String jsonStr) {
        Log.d(TAG, "<UpdateGame> Received unity message: " + jsonStr);
        ComboSDK.getInstance().updateGame(UnityPlayer.currentActivity, gson.fromJson(jsonStr, ComboSDKUpdateGameOptions.class), result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<UpdateGame> Send message to unity: " + resultStr);
                SendJson("_UpdateGameSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<UpdateGame> Send message to unity: " + resultStr);
                SendJson("_UpdateGameFailed", resultStr);
            }
        });
    }
    
    public static void GetDownloadUrl() {
        Log.d(TAG, "<GetDownloadUrl> Received unity message: null");
        ComboSDK.getInstance().getDownloadUrl(result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<GetDownloadUrl> Send message to unity: " + resultStr);
                SendJson("_GetDownloadUrlSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<GetDownloadUrl> Send message to unity: " + resultStr);
                SendJson("_GetDownloadUrlFailed", resultStr);
            }
        });
    }
    
    public static void Quit() {
        Log.d(TAG, "<Quit> Received unity message: null");
        ComboSDK.getInstance().quit(UnityPlayer.currentActivity, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Quit> Send message to unity: " + resultStr);
                SendJson("_QuitSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Quit> Send message to unity: " + resultStr);
                SendJson("_QuitFailed", resultStr);
            }
        });
    }
    
    public static void ReportCreateRole(String jsonStr) {
        Log.d(TAG, "<ReportCreateRole> Received unity message: " + jsonStr);
        ComboSDK.getInstance().reportCreateRole(gson.fromJson(jsonStr, ComboSDKRoleInfo.class));
    }

    public static void ReportEnterGame(String jsonStr) {
        Log.d(TAG, "<ReportEnterGame> Received unity message: " + jsonStr);
        ComboSDK.getInstance().reportEnterGame(gson.fromJson(jsonStr, ComboSDKRoleInfo.class));
    }

    public static String GetVersion() {
        Log.d(TAG, "<GetVersion> Received unity message: null");
        return ComboSDK.getInstance().getVersion();
    }

    public static String GetDistro() {
        Log.d(TAG, "<GetDistro> Received unity message: null");
        return ComboSDK.getInstance().getDistro();
    }

    public static String GetDeviceId() {
        Log.d(TAG, "<GetDeviceId> Received unity message: null");
        return ComboSDK.getInstance().getDeviceId();
    }

    public static String GetVariant() {
        Log.d(TAG, "<GetVariant> Received unity message: null");
        return ComboSDK.getInstance().getVariant();
    }

    public static String GetSubvariant() {
        Log.d(TAG, "<GetSubvariant> Received unity message: null");
        return ComboSDK.getInstance().getSubvariant();
    }
    
    public static String GetParameters() {
        Log.d(TAG, "<GetParameters> Received unity message: null");
        return gson.toJson(ComboSDK.getInstance().getParameters());
    }

    public static void OpenAppSettings() {
        Log.d(TAG, "<OpenAppSettings> Received unity message: null");
        ComboSDK.getInstance().openAppSettings(UnityPlayer.currentActivity);
    }

    public static String GetUserId() {
        Log.d(TAG, "<GetUserId> Received unity message: null");
        return ComboSDK.SeayooAccount.getUserId();
    }

    public static void ManageAccount() {
        Log.d(TAG, "<ManageAccount> Received unity message: null");
        ComboSDK.SeayooAccount.manageAccount(UnityPlayer.currentActivity);
    }

    public static void ChangePassword() {
        Log.d(TAG, "<ChangePassword> Received unity message: null");
        ComboSDK.SeayooAccount.changePassword(UnityPlayer.currentActivity);
    }

    public static void DeleteAccount() {
        Log.d(TAG, "<DeleteAccount> Received unity message: null");
        ComboSDK.SeayooAccount.deleteAccount(UnityPlayer.currentActivity);
    }

    public static void ContactSupport() {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<ContactSupport> Received unity message: null");
        ComboSDK.getInstance().contactSupport(UnityPlayer.currentActivity);
    }

    public static void OpenGameUrl(int value) {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<OpenGameUrl> Received unity message: " + value);
        GameUrl url;
        switch (value) {
            case 0:
                url = GameUrl.USER_AGREEMENT;
                break;
            case 1:
                url = GameUrl.PRIVACY_POLICY;
                break;
            case 2:
                url = GameUrl.PRIVACY_CHILDREN;
                break;
            case 3:
                url = GameUrl.THIRD_PARTY;
                break;
            case 4:
                url = GameUrl.FANGCHENMI;
                break;
            default:
                return;
        }
        ComboSDK.getInstance().openGameUrl(UnityPlayer.currentActivity, url);
    }

    public static void OpenShortLink(String shortLink, String gameData) {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<OpenShortLink> Received unity message: null");

        Gson gson = new Gson();
        Type type = new TypeToken<Map<String, String>>(){}.getType();
        Map<String, String> map = gson.fromJson(gameData, type);

        ComboSDK.getInstance().openShortLink(UnityPlayer.currentActivity, shortLink, map, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<OpenShortLink> Send message to unity: " + resultStr);
                SendJson("_OpenShortLinkSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<OpenShortLink> Send message to unity: " + resultStr);
                SendJson("_OpenShortLinkFailed", resultStr);
            }
        });
    }

    public static void CheckAnnouncements(String jsonStr)
    {
        Log.d(TAG, "<CheckAnnouncements> Received unity message: " + jsonStr);
        CheckAnnouncementsOptions opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), CheckAnnouncementsOptions.class);
        ComboSDK.getInstance().checkAnnouncements(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<CheckAnnouncements> Send message to unity: " + resultStr);
                SendJson("_CheckAnnouncementsSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<CheckAnnouncements> Send message to unity: " + resultStr);
                SendJson("_CheckAnnouncementsFailed", resultStr);
            }
        });
    }

    public static void OpenAnnouncements(String jsonStr)
    {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<OpenAnnouncements> Received unity message: " + jsonStr);
        OpenAnnouncementsOptions opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), OpenAnnouncementsOptions.class);
        ComboSDK.getInstance().openAnnouncements(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<OpenAnnouncements> Send message to unity: " + resultStr);
                SendJson("_OpenAnnouncementsSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<OpenAnnouncements> Send message to unity: " + resultStr);
                SendJson("_OpenAnnouncementsFailed", resultStr);
            }
        });
    }

    public static void Complain(String jsonStr)
    {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<Complain> Received unity message: " + jsonStr);
        ComplainOptions opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), ComplainOptions.class);
        ComboSDK.getInstance().complain(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<Complain> Send message to unity: " + resultStr);
                SendJson("_ComplainSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<Complain> Send message to unity: " + resultStr);
                SendJson("_ComplainFailed", resultStr);
            }
        });
    }

    public static void PromoPseudoPurchase(String jsonStr)
    {
        Log.d(TAG, "<PromoPseudoPurchase> Received unity message: null");
        PromoPseudoPurchaseOptions opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), PromoPseudoPurchaseOptions.class);
        ComboSDK.getInstance().promoPseudoPurchase(UnityPlayer.currentActivity, opts);
    }

    public static boolean ResetGuest()
    {
        Log.d(TAG, "<ResetGuest> Received unity message: null");
        return ComboSDK.getInstance().resetGuest(UnityPlayer.currentActivity);
    }

    public static String GetLanguagePreference()
    {
        Log.d(TAG, "<GetLanguagePreference> Received unity message: null");
        String result = gson.toJson(ComboSDK.getInstance().getLanguagePreference(UnityPlayer.currentActivity));
        return result;
    }

    public static void SetLanguagePreference(int value)
    {
        Log.d(TAG, "<SetLanguagePreference> Received unity message: " + value);
        LanguagePreference language;
        switch (value) {
            case 0:
                language = LanguagePreference.FollowSystem;
                break;
            case 1:
                language = LanguagePreference.ChineseSimplified;
                break;
            case 2:
                language = LanguagePreference.English;
                break;
            default:
                return;
        }
        ComboSDK.getInstance().setLanguagePreference(UnityPlayer.currentActivity, language);
    }

    public static String GetLanguageCode()
    {
        Log.d(TAG, "<GetLanguageCode> Received unity message: null");
        String result = gson.toJson(ComboSDK.getInstance().getLanguageCode(UnityPlayer.currentActivity));
        return result;
    }

    public static void RedeemGiftCode(String jsonStr)
    {
        SetKeepRenderingOnPause();
        Log.d(TAG, "<RedeemGiftCode> Received unity message: " + jsonStr);
        RedeemGiftCodeOptions opts = gson.fromJson(convertFirstCharToLowerCase(jsonStr), RedeemGiftCodeOptions.class);
        ComboSDK.getInstance().redeemGiftCode(UnityPlayer.currentActivity, opts, result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.d(TAG, "<RedeemGiftCode> Send message to unity: " + resultStr);
                SendJson("_RedeemGiftCodeSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.d(TAG, "<RedeemGiftCode> Send message to unity: " + resultStr);
                SendJson("_RedeemGiftCodeFailed", resultStr);
            }
        });
    }

    public static void ReportDouyinCustomEvent(String eventName, String eventParams)
    {
        Log.d(TAG, "<ReportDouyinCustomEvent> Received unity message: " + "eventName: " + eventName + "eventParams: " + eventParams);

        Gson gson = new Gson();
        Type type = new TypeToken<Map<String, String>>(){}.getType();
        Map<String, String> map = gson.fromJson(eventParams, type);

        ComboSDK.getInstance().reportDouyinCustomEvent(eventName, map);
    }
    
    private static void RegisterKickOut() {
        ComboSDK.getInstance().registerKickOut(result -> {
            if (result.isSuccess()) {
                String resultStr = gson.toJson(result.get());
                Log.i(TAG, "<OnKickOut> Send message to unity: " + resultStr);
                SendJson("_KickOutSucceed", resultStr);
            } else {
                String resultStr = gson.toJson(result.error());
                Log.i(TAG, "<OnKickOut> Send message to unity: " + resultStr);
                SendJson("_KickOutFailed", resultStr);
            }
        });
    }

    private static void SendJson(String method, String jsonStr) {
        UnityPlayer.UnitySendMessage("ComboSDKAndroidBridge", method, jsonStr);
    }
    static class ComboSDKShareSceneDeserializer implements JsonDeserializer<ComboSDKShareScene> {
        @Override
        public ComboSDKShareScene deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            int typeInt = json.getAsInt();
            switch (typeInt) {
                case 1:
                    return ComboSDKShareScene.WEIXIN_TIMELINE;
                case 2:
                    return ComboSDKShareScene.WEIXIN_FAVORITE;
                case 3:
                    return ComboSDKShareScene.DOUYIN_EDIT;
                case 4:
                    return ComboSDKShareScene.DOUYIN_PUBLISH;
                case 5:
                    return ComboSDKShareScene.DOUYIN_CONTACTS;
                case 6:
                    return ComboSDKShareScene.QQ;
                case 7:
                    return ComboSDKShareScene.QQ_QZONE;
                default:
                    return ComboSDKShareScene.WEIXIN_SESSION;
            }
        }
    }

    static class ComboSDKShareTargetDeserializer implements JsonDeserializer<ComboSDKShareTarget> {
        @Override
        public ComboSDKShareTarget deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            int typeInt = json.getAsInt();
            switch (typeInt) {
                case 1:
                    return ComboSDKShareTarget.TAPTAP;
                case 2:
                    return ComboSDKShareTarget.AGORA;
                case 3:
                    return ComboSDKShareTarget.WEIXIN;
                case 4:
                    return ComboSDKShareTarget.WEIBO;
                case 5:
                    return ComboSDKShareTarget.DOUYIN;
                case 6:
                    return ComboSDKShareTarget.QQ;
                default:
                    return ComboSDKShareTarget.SYSTEM;
            }
        }
    }
    public static String convertFirstCharToLowerCase(String jsonString) {
        // 使用StringBuilder，它比StringBuffer有更好的性能
        StringBuilder result = new StringBuilder(jsonString.length());
        boolean shouldConvertNextCharToLower = false;

        for (char character : jsonString.toCharArray()) {
            // 检查字符是否在双引号之后
            if (shouldConvertNextCharToLower && Character.isUpperCase(character)) {
                result.append(Character.toLowerCase(character));
                shouldConvertNextCharToLower = false; // 重置标志
            } else {
                result.append(character);
                shouldConvertNextCharToLower = (character == '\"'); // 当遇到双引号时设置标志
            }
        }
        return result.toString();
    }

    /**
     *  JSON 字段兼容
     */
    public static String getAdaptedJsonStr(String jsonStr, String newKey, String[] legacyKeys) {
        try {
            Gson gson = new Gson();
            JsonObject jsonObject = JsonParser.parseString(jsonStr).getAsJsonObject();
            
            for (String legacyKey : legacyKeys) {
                if (jsonObject.has(legacyKey) && !jsonObject.get(legacyKey).isJsonNull() 
                    && !jsonObject.get(legacyKey).getAsString().isEmpty()) {
                    jsonObject.add(newKey, jsonObject.get(legacyKey));
                    jsonObject.remove(legacyKey);
                    break;
                }
            }
            
            return gson.toJson(jsonObject);
        } catch (JsonSyntaxException | IllegalStateException e) {
            // Log the error if needed
            Log.e(TAG, "Failed to adapt JSON string: " + e.getMessage());
            return jsonStr;
        }
    }

    private static boolean isKeepRenderingOnPause = false;

    /**
     *  UnityPlayer onPause中继续渲染
     */
    public static void KeepRenderingOnPause() {
        Log.i(TAG, "KeepRenderingOnPause");
        isKeepRenderingOnPause = true;
    }

    /**
     * 设置是否在下一次onPause中继续渲染
     */
    private static void SetKeepRenderingOnPause(){
        try {
            Log.i(TAG, "SetKeepRenderingOnPause: " + isKeepRenderingOnPause);
            ComboSDKMainActivity unityActivity = (ComboSDKMainActivity)UnityPlayer.currentActivity;
            unityActivity.isKeepRenderingOnPause = isKeepRenderingOnPause;
        } catch (NullPointerException | ClassCastException e) {
            Log.e(TAG, "SetKeepRenderingOnPause: " + e);
        }
    }
}
