#if UNITY_WEBGL
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using Seayoo.LitJson;

namespace Combo.Platform
{
    public class NativeWebGL : MonoBehaviour
    {
        private static Action<Result<SetupResult>> setupFinishedAction;
        private static Action<Result<LoginResult>> loginFinishedAction;
        private static Action<Result<PurchaseResult>> purchaseFinishedAction;
        private static Action<Result<PreloadAdResult>> preloadAdFinishedAction;
        private static Action<Result<ShowAdResult>> showAdFinishedAction;
        private static Action<Result<GetAnnouncementsResult>> getAnnouncementsFinishedAction;
        private static Action<Result<CheckAnnouncementsResult>> checkAnnouncementsFinishedAction;
        private static Action<Result<ComplainResult>> complainFinishedAction;
        private static Action<Result<OpenShortLinkResult>> openShortLinkFinishedAction;
        private static Action<Result<RedeemGiftCodeResult>> redeemGiftCodeFinishedAction;

        [DllImport("__Internal")]
        private static extern void freeMemory(IntPtr pointer);

        [DllImport("__Internal")]
        private static extern void setup(string strJsonData);
        public static void Setup(SetupOptions opts, Action<Result<SetupResult>> callback)
        {
            GameObject obj = GameObject.Find("ComboSDKWebGL");

            if (obj == null)
            {
                obj = new GameObject("ComboSDKWebGL", typeof(NativeWebGL));
                DontDestroyOnLoad(obj);
            }
            setupFinishedAction = callback;
            setup(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void login();
        public static void Login(Action<Result<LoginResult>> callback)
        {
            loginFinishedAction = callback;
            login();
        }

        [DllImport("__Internal")]
        private static extern IntPtr getParameters();
        public static Dictionary<string, string> GetParameters()
        {
            var resultPtr = getParameters();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            var parameters = JsonMapper.ToObject<Dictionary<string, string>>(jsonString);
            freeMemory(resultPtr);
            return parameters;
        }

        [DllImport("__Internal")]
        public static extern void purchase(string strJsonData);
        public static void Purchase(PurchaseOptions opts, Action<Result<PurchaseResult>> callback)
        {
            purchaseFinishedAction = callback;
            purchase(opts.ToJson());
        }

        [DllImport("__Internal")]
        public static extern bool isFeatureAvailable(int feature);
        public static bool IsFeatureAvailable(Feature feature)
        {
            return isFeatureAvailable((int)feature);
        }

        [DllImport("__Internal")]
        public static extern void contactSupport();
        public static void ContactSupport()
        {
            contactSupport();
        }

        [DllImport("__Internal")]
        public static extern IntPtr getLoginInfo();
        public static LoginInfo GetLoginInfo()
        {
            var resultPtr = getLoginInfo();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            var info = JsonMapper.ToObject<LoginInfo>(jsonString);
            freeMemory(resultPtr);
            return info;
        }

        [DllImport("__Internal")]
        public static extern IntPtr getUserId();
        public static string GetUserId()
        {
            var resultPtr = getUserId();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            freeMemory(resultPtr);
            return jsonString;
        }

        [DllImport("__Internal")]
        public static extern IntPtr getDistro();
        public static string GetDistro()
        {
            var resultPtr = getDistro();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            freeMemory(resultPtr);
            return jsonString;
        }

        [DllImport("__Internal")]
        public static extern IntPtr getVersion();
        public static string GetVersion()
        {
            var resultPtr = getVersion();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            freeMemory(resultPtr);
            return jsonString;
        }

        [DllImport("__Internal")]
        public static extern IntPtr getDeviceId();
        public static string GetDeviceId()
        {
            var resultPtr = getDeviceId();
            string jsonString = Marshal.PtrToStringAuto(resultPtr);
            freeMemory(resultPtr);
            return jsonString;
        }

        [DllImport("__Internal")]
        private static extern void reportCreateRole(string strJsonData);
        public static void ReportCreateRole(RoleInfo roleInfo)
        {
            reportCreateRole(roleInfo.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void preloadAd(string strJsonData);
        public static void PreloadAd(PreloadAdOptions opts, Action<Result<PreloadAdResult>> callback)
        {
            preloadAdFinishedAction = callback;
            preloadAd(opts.ToJson());
        }   

        [DllImport("__Internal")]
        private static extern void showAd(string strJsonData);
        public static void ShowAd(ShowAdOptions opts, Action<Result<ShowAdResult>> callback)
        {
            showAdFinishedAction = callback;
            showAd(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void getAnnouncements(string strJsonData);
        public static void GetAnnouncements(GetAnnouncementsOptions opts, Action<Result<GetAnnouncementsResult>> callback)
        {
            Debug.Log($"[NativeWebGL] GetAnnouncements: {opts.ToJson()}");
            getAnnouncementsFinishedAction = callback;
            getAnnouncements(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void checkAnnouncements(string strJsonData);
        public static void CheckAnnouncements(CheckAnnouncementsOptions opts, Action<Result<CheckAnnouncementsResult>> callback)
        {
            Debug.Log($"[NativeWebGL] CheckAnnouncements: {opts.ToJson()}");
            checkAnnouncementsFinishedAction = callback;
            checkAnnouncements(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void complain(string strJsonData);
        public static void Complain(ComplainOptions opts, Action<Result<ComplainResult>> callback)
        {
            Debug.Log($"[NativeWebGL] Complain: {opts.ToJson()}");
            complainFinishedAction = callback;
            complain(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void redeemGiftCode(string strJsonData);
        public static void RedeemGiftCode(RedeemGiftCodeOptions opts, Action<Result<RedeemGiftCodeResult>> callback)
        {
            redeemGiftCodeFinishedAction = callback;
            redeemGiftCode(opts.ToJson());
        }

        [DllImport("__Internal")]
        private static extern void openShortLink(string shortLink, string gameData);
        public static void OpenShortLink(string shortLink, Dictionary<string, string> gameData, Action<Result<OpenShortLinkResult>> callback)
        {
            Debug.Log($"[NativeWebGL] OpenShortLink: {shortLink}");
            openShortLinkFinishedAction = callback;
            openShortLink(shortLink, JsonMapper.ToJson(gameData ?? new Dictionary<string, string>()));
        }

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

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

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

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

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

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

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

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

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

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

        public void _GetAnnouncementsSucceed(string msg)
        {
            Debug.Log($"[NativeWebGL] _GetAnnouncementsSucceed: {msg}");
            var result = Result<GetAnnouncementsResult>.CreateSuccessFromJson(msg);
            getAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _GetAnnouncementsFailed(string msg)
        {
            Debug.Log($"[NativeWebGL] _GetAnnouncementsFailed: {msg}");
            var result = Result<GetAnnouncementsResult>.CreateFailFromJson(msg);
            getAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _CheckAnnouncementsSucceed(string msg)
        {
            Debug.Log($"[NativeWebGL] _CheckAnnouncementsSucceed: {msg}");
            var result = Result<CheckAnnouncementsResult>.CreateSuccessFromJson(msg);
            checkAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _CheckAnnouncementsFailed(string msg)
        {
            Debug.Log($"[NativeWebGL] _CheckAnnouncementsFailed: {msg}");
            var result = Result<CheckAnnouncementsResult>.CreateFailFromJson(msg);
            checkAnnouncementsFinishedAction?.Invoke(result);
        }

        public void _ComplainSucceed(string msg)
        {
            Debug.Log($"[NativeWebGL] _ComplainSucceed: {msg}");
            var result = Result<ComplainResult>.CreateSuccessFromJson(msg);
            complainFinishedAction?.Invoke(result);
        }

        public void _ComplainFailed(string msg)
        {
            Debug.Log($"[NativeWebGL] _ComplainFailed: {msg}");
            var result = Result<ComplainResult>.CreateFailFromJson(msg);
            complainFinishedAction?.Invoke(result);
        }

        public void _RedeemGiftCodeSucceed(string msg)
        {
            Debug.Log($"[NativeWebGL] _RedeemGiftCodeSucceed: {msg}");
            var result = Result<RedeemGiftCodeResult>.CreateSuccessFromJson(msg);
            redeemGiftCodeFinishedAction?.Invoke(result);
        }

        public void _RedeemGiftCodeFailed(string msg)
        {
            Debug.Log($"[NativeWebGL] _RedeemGiftCodeFailed: {msg}");
            var result = Result<RedeemGiftCodeResult>.CreateFailFromJson(msg);
            redeemGiftCodeFinishedAction?.Invoke(result);
        }

        public void _OpenShortLinkSucceed(string msg)
        {
            Debug.Log($"[NativeWebGL] _OpenShortLinkSucceed: {msg}");
            var result = Result<OpenShortLinkResult>.CreateSuccessFromJson(msg);
            openShortLinkFinishedAction?.Invoke(result);
        }

        public void _OpenShortLinkFailed(string msg)
        {
            Debug.Log($"[NativeWebGL] _OpenShortLinkFailed: {msg}");
            var result = Result<OpenShortLinkResult>.CreateFailFromJson(msg);
            openShortLinkFinishedAction?.Invoke(result);
        }
    }
}
#endif
