#if UNITY_ANDROID
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;

using ThinkingData.Analytics;
using Sentry;

namespace Combo.Platform
{
    public class NativeAndroid : MonoBehaviour
    {
        private const string ANDROID_BRIDGE_OBJ = "ComboSDKAndroidBridge";

        private static readonly AndroidJavaClass jBridge = new AndroidJavaClass(
            "com.seayoo.sdk.ComboSDKAndroidWrapper"
        );

        private static Action<Result<SetupResult>> setupFinishedAction;
        private static Action<Result<LoginResult>> loginFinishedAction;
        private static Action<Result<LogoutResult>> logoutFinishedAction;
        private static Action<Result<PurchaseResult>> purchaseFinishedAction;
        private static Action<Result<PreloadAdResult>> preloadAdFinishedAction;
        private static Action<Result<ShowAdResult>> showAdFinishedAction;
        private static Action<Result<KickOutResult>> kickOutFinishedAction;
        private static Action<Result<ShareResult>> shareFinishedAction;
        private static Action<Result<UpdateGameResult>> updateGameFinishedAction;
        private static Action<Result<DownloadUrlResult>> downloadUrlFinishedAction;
        private static Action<Result<QuitResult>> quitFinishedAction;
        private static Action<Result<OpenShortLinkResult>> openShortLinkFinishedAction;
        private static Action<Result<CheckAnnouncementsResult>> checkAnnouncementsFinishedAction;
        private static Action<Result<OpenAnnouncementsResult>> openAnnouncementsFinishedAction;
        private static Action<Result<ComplainResult>> complainFinishedAction;
        private static Action<Result<RedeemGiftCodeResult>> redeemGiftCodeFinishedAction;

        [RuntimeInitializeOnLoadMethod]
        private static void GameOnLoad()
        {
            GameObject existingObject = GameObject.Find(ANDROID_BRIDGE_OBJ);
            if (existingObject == null)
            {
                var jBridgeObj = new GameObject(ANDROID_BRIDGE_OBJ, typeof(NativeAndroid));
                DontDestroyOnLoad(jBridgeObj);
            }
        }

        #region NativeMessageReceivers
        public void _SetupSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<SetupResult>.CreateSuccessFromJson(msg);
            setupFinishedAction?.Invoke(result);
        }

        public void _SetupFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<SetupResult>.CreateFailFromJson(msg);
            setupFinishedAction?.Invoke(result);
        }

        public void _LoginSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<LoginResult>.CreateSuccessFromJson(msg);

            if (result != null)
            {
                var comboId = result.Data.loginInfo.comboId;
                TDAnalytics.Login(comboId);
                SentrySdk.ConfigureScope(scope =>
                {
                    scope.User.Id = comboId;
                });
            }

            loginFinishedAction?.Invoke(result);
        }

        public void _LoginFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<LoginResult>.CreateFailFromJson(msg);
            loginFinishedAction?.Invoke(result);
        }

        public void _LogoutSucceed(string msg)
        {
            DebugLog(msg);
            TDAnalytics.Logout();
            var result = Result<LogoutResult>.CreateSuccessFromJson(msg);
            logoutFinishedAction?.Invoke(result);
        }

        public void _LogoutFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<LogoutResult>.CreateFailFromJson(msg);
            logoutFinishedAction?.Invoke(result);
        }

        public void _PurchaseSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<PurchaseResult>.CreateSuccessFromJson(msg);
            purchaseFinishedAction?.Invoke(result);
        }

        public void _PurchaseFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<PurchaseResult>.CreateFailFromJson(msg);
            purchaseFinishedAction?.Invoke(result);
        }

        public void _PreloadAdSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<PreloadAdResult>.CreateSuccessFromJson(msg);
            preloadAdFinishedAction?.Invoke(result);
        }

        public void _PreloadAdFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<PreloadAdResult>.CreateFailFromJson(msg);
            preloadAdFinishedAction?.Invoke(result);
        }

        public void _ShowAdSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<ShowAdResult>.CreateSuccessFromJson(msg);
            showAdFinishedAction?.Invoke(result);
        }

        public void _ShowAdFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<ShowAdResult>.CreateFailFromJson(msg);
            showAdFinishedAction?.Invoke(result);
        }

        public void _KickOutSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<KickOutResult>.CreateSuccessFromJson(msg);
            kickOutFinishedAction?.Invoke(result);
        }

        public void _KickOutFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<KickOutResult>.CreateFailFromJson(msg);
            kickOutFinishedAction?.Invoke(result);
        }

        public void _ShareSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<ShareResult>.CreateSuccessFromJson(msg);
            shareFinishedAction?.Invoke(result);
        }

        public void _ShareFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<ShareResult>.CreateFailFromJson(msg);
            shareFinishedAction?.Invoke(result);
        }

        public void _UpdateGameSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<UpdateGameResult>.CreateSuccessFromJson(msg);
            updateGameFinishedAction?.Invoke(result);
        }

        public void _UpdateGameFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<UpdateGameResult>.CreateFailFromJson(msg);
            updateGameFinishedAction?.Invoke(result);
        }

        public void _GetDownloadUrlSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<DownloadUrlResult>.CreateSuccessFromJson(msg);
            downloadUrlFinishedAction?.Invoke(result);
        }

        public void _GetDownloadUrlFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<DownloadUrlResult>.CreateFailFromJson(msg);
            downloadUrlFinishedAction?.Invoke(result);
        }

        public void _QuitSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<QuitResult>.CreateSuccessFromJson(msg);
            quitFinishedAction?.Invoke(result);
        }

        public void _QuitFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<QuitResult>.CreateFailFromJson(msg);
            quitFinishedAction?.Invoke(result);
        }

        public void _OpenShortLinkSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<OpenShortLinkResult>.CreateSuccessFromJson(msg);
            openShortLinkFinishedAction?.Invoke(result);
        }

        public void _OpenShortLinkFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<OpenShortLinkResult>.CreateFailFromJson(msg);
            openShortLinkFinishedAction?.Invoke(result);
        }
        public void _CheckAnnouncementsSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<CheckAnnouncementsResult>.CreateSuccessFromJson(msg);
            checkAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _CheckAnnouncementsFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<CheckAnnouncementsResult>.CreateFailFromJson(msg);
            checkAnnouncementsFinishedAction?.Invoke(result);
        }
        public void _OpenAnnouncementsSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<OpenAnnouncementsResult>.CreateSuccessFromJson(msg);
            openAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _OpenAnnouncementsFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<OpenAnnouncementsResult>.CreateFailFromJson(msg);
            openAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _ComplainSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<ComplainResult>.CreateSuccessFromJson(msg);
            complainFinishedAction?.Invoke(result);
        }

        public void _ComplainFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<ComplainResult>.CreateFailFromJson(msg);
            complainFinishedAction?.Invoke(result);
        }

        public void _RedeemGiftCodeSucceed(string msg)
        {
            DebugLog(msg);
            var result = Result<RedeemGiftCodeResult>.CreateSuccessFromJson(msg);
            redeemGiftCodeFinishedAction?.Invoke(result);
        }

        public void _RedeemGiftCodeFailed(string msg)
        {
            DebugLog(msg);
            var result = Result<RedeemGiftCodeResult>.CreateFailFromJson(msg);
            redeemGiftCodeFinishedAction?.Invoke(result);
        }


        #endregion

        #region NativeMethodCallers

        public static void OnKickOut(Action<Result<KickOutResult>> callback)
        {
            kickOutFinishedAction = callback;
            jBridge.CallStatic("RegisterKickOut");
        }

        public static void Setup(SetupOptions opts, Action<Result<SetupResult>> callback)
        {
            setupFinishedAction = callback;
            jBridge.CallStatic("Setup", opts.ToJson());
        }

        public static void Login(Action<Result<LoginResult>> callback)
        {
            loginFinishedAction = callback;
            jBridge.CallStatic("Login");
        }

        public static LoginInfo GetLoginInfo()
        {
            var r = jBridge.CallStatic<string>("GetLoginInfo");
            DebugLog("GetLoginInfo " + r);
            if (r == null)
                return null;
            return Result<LoginInfo>.CreateSuccessFromJson(r).Data;
        }

        public static void Logout(Action<Result<LogoutResult>> callback)
        {
            logoutFinishedAction = callback;
            jBridge.CallStatic("Logout");
        }

        public static void Purchase(PurchaseOptions opts, Action<Result<PurchaseResult>> callback)
        {
            purchaseFinishedAction = callback;
            jBridge.CallStatic("Purchase", opts.ToJson());
        }

        public static void PreloadAd(PreloadAdOptions opts, Action<Result<PreloadAdResult>> callback)
        {
            preloadAdFinishedAction = callback;
            jBridge.CallStatic("PreloadAd", opts.ToJson());
        }


        public static void ShowAd(ShowAdOptions opts, Action<Result<ShowAdResult>> callback)
        {
            showAdFinishedAction = callback;
            jBridge.CallStatic("ShowAd", opts.ToJson());
        }

        public static void Share(ShareOptions opts, Action<Result<ShareResult>> callback)
        {
            shareFinishedAction = callback;
            jBridge.CallStatic("Share", opts.GetType().Name, opts.ToJson());
        }

        public static void ReportCreateRole(RoleInfo roleInfo)
        {
            jBridge.CallStatic("ReportCreateRole", roleInfo.ToJson());
        }

        public static void ReportEnterGame(RoleInfo roleInfo)
        {
            jBridge.CallStatic("ReportEnterGame", roleInfo.ToJson());
        }

        public static void Quit(Action<Result<QuitResult>> callback)
        {
            quitFinishedAction = callback;
            jBridge.CallStatic("Quit");
        }

        public static ShareTarget[] GetAvailableShareTargets()
        {
            return JsonConvert.DeserializeObject<ShareTarget[]>(jBridge.CallStatic<string>("GetAvailableShareTargets"));
        }

        public static string GetDistro()
        {
            return jBridge.CallStatic<string>("GetDistro");
        }
        public static string GetVersion()
        {
            return jBridge.CallStatic<string>("GetVersion");
        }
        public static string GetDeviceId()
        {
            return jBridge.CallStatic<string>("GetDeviceId");
        }
        public static string GetVariant()
        {
            return jBridge.CallStatic<string>("GetVariant");
        }
        public static string GetSubvariant()
        {
            return jBridge.CallStatic<string>("GetSubvariant");
        }
        public static void GetDownloadUrl(Action<Result<DownloadUrlResult>> callback)
        {
            downloadUrlFinishedAction = callback;
            jBridge.CallStatic("GetDownloadUrl");
        }
        public static bool IsFeatureAvailable(Feature feature)
        {
            return jBridge.CallStatic<bool>("IsFeatureAvailable", (int)feature);
        }
        public static void UpdateGame(UpdateGameOptions opts, Action<Result<UpdateGameResult>> callback)
        {
            updateGameFinishedAction = callback;
            jBridge.CallStatic("UpdateGame", opts.ToJson());
        }

        public static Dictionary<string, string> GetParameters()
        {
            return JsonConvert.DeserializeObject<Dictionary<string, string>>(jBridge.CallStatic<string>("GetParameters"));
        }

        public static void OpenAppSettings()
        {
            jBridge.CallStatic("OpenAppSettings");
        }

        public static string GetUserId()
        {
            return jBridge.CallStatic<string>("GetUserId");
        }

        public static void ManageAccount()
        {
            jBridge.CallStatic("ManageAccount");
        }

        public static void ChangePassword()
        {
            jBridge.CallStatic("ChangePassword");
        }

        public static void DeleteAccount()
        {
            jBridge.CallStatic("DeleteAccount");
        }

        public static void ContactSupport()
        {
            jBridge.CallStatic("ContactSupport");
        }

        public static void OpenGameUrl(GameUrl url)
        {
            jBridge.CallStatic("OpenGameUrl", (int)url);
        }

        public static void OpenShortLink(string shortLink, Dictionary<string, string> gameData, Action<Result<OpenShortLinkResult>> callback)
        {
            openShortLinkFinishedAction = callback;
            jBridge.CallStatic("OpenShortLink", shortLink, JsonConvert.SerializeObject(gameData));
        }

        public static void CheckAnnouncements(CheckAnnouncementsOptions opts, Action<Result<CheckAnnouncementsResult>> callback)
        {
            checkAnnouncementsFinishedAction = callback;
            jBridge.CallStatic("CheckAnnouncements", opts.ToJson());
        }

        public static void OpenAnnouncements(OpenAnnouncementsOptions opts, Action<Result<OpenAnnouncementsResult>> callback)
        {
            openAnnouncementsFinishedAction = callback;
            jBridge.CallStatic("OpenAnnouncements", opts.ToJson());
        }

        public static void KeepRenderingOnPause() 
        {
            jBridge.CallStatic("KeepRenderingOnPause");
        }

        public static void PromoPseudoPurchase(PromoPseudoPurchaseOptions opts)
        {
            jBridge.CallStatic("PromoPseudoPurchase", opts.ToJson());
        }

        public static void Complain(ComplainOptions opts, Action<Result<ComplainResult>> callback)
        {
            complainFinishedAction = callback;
            jBridge.CallStatic("Complain", opts.ToJson());
        }

        public static LanguagePreference GetLanguagePreference()
        {
            return JsonConvert.DeserializeObject<LanguagePreference>(jBridge.CallStatic<string>("GetLanguagePreference"));
        }

        public static void SetLanguagePreference(LanguagePreference languagePreference)
        {
            jBridge.CallStatic("SetLanguagePreference", (int)languagePreference);
        }

        public static string GetLanguageCode()
        {
            return jBridge.CallStatic<string>("GetLanguageCode");
        }
    
        public static bool ResetGuest()
        {
            return jBridge.CallStatic<bool>("ResetGuest");
        }


        public static void RedeemGiftCode(RedeemGiftCodeOptions opts, Action<Result<RedeemGiftCodeResult>> callback)
        {
            redeemGiftCodeFinishedAction = callback;
            jBridge.CallStatic("RedeemGiftCode", opts.ToJson());
        }

        #endregion

        private static void DebugLog(string msg)
        {
            //Debug.LogWarning("Android: " + msg);
        }
    }
}
#endif
