using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Newtonsoft.Json.Linq;
using UnityEngine.Scripting;

namespace TyphoonUnitySDK
{
    /// <summary>
    /// 调用Oppo小游戏原生API
    /// </summary>
    [Preserve]
    public class OppoNative : MonoSingleton<OppoNative>
    {
        [DllImport("__Internal")]
        private static extern void OppoNativeCall(string msg);


        [DllImport("__Internal")]
        private static extern string OppoNativeCallReturn(string msg);

        //调用原生方法
        public static void Call(SessionItem session)
        {
            var send = new
            {
                session = session.SessionId,
                method = session.MethodName,
                data = session.SendData,
            };
            OppoNativeCall(send.ToXJson());
        }

        //带返回值调用
        public static string CallReturn(string method, object input)
        {
            var send = new
            {
                method,
                data = input,
            };
            return OppoNativeCallReturn(send.ToXJson());
        }

        protected override void Init()
        {
            base.Init();
            DontDestroyOnLoad(gameObject);
            SdkDebug.Log("OppoNative Init");
            gameObject.name = "TYPHOON_OPPO_NATIVE";
        }

        /*处理session消息*/
        public void OnReceiveSessionCallback(string json)
        {
            SdkDebug.Log($"[OppoNative] OnReceiveSessionCallback {json}");
            var jObject = JObject.Parse(json);
            var sessionId = jObject["sessionId"].ToLong();
            var data = jObject["data"]?.ToObject<string>();
            SessionItem.Invoke(sessionId, data);
        }

        #region 小游戏端模拟 PlayerPrefs

        private struct CacheItem
        {
            public object Value;
            public bool IsDelete;
        }

        [Serializable]
        private class StorageItem
        {
            public string key;
            public object value;

            public StorageItem(string key, object value)
            {
                this.key = key;
                this.value = value;
            }
        }

        //缓存数据
        private Dictionary<string, CacheItem> _cache = new Dictionary<string, CacheItem>();

        private void SetItemToCache(string key, int value)
        {
            _cache[key] = new CacheItem()
            {
                Value = value,
                IsDelete = false,
            };
        }

        private void SetItemToCache(string key, float value)
        {
            _cache[key] = new CacheItem()
            {
                Value = value,
                IsDelete = false,
            };
        }

        private void SetItemToCache(string key, string value)
        {
            _cache[key] = new CacheItem()
            {
                Value = value,
                IsDelete = false,
            };
        }

        private void RemoveItemFromCache(string key)
        {
            _cache[key] = new CacheItem()
            {
                IsDelete = true,
            };
        }


        /// <summary>
        /// 设置float
        /// </summary>
        public void PlayerPrefs_SetFloat(string key, float defaultValue)
        {
            //设置到缓存
            SetItemToCache(key, defaultValue);
        }

        /// <summary>
        /// 设置int
        /// </summary>
        public void PlayerPrefs_SetInt(string key, int defaultValue)
        {
            //设置到缓存
            SetItemToCache(key, defaultValue);
        }

        /// <summary>
        /// 设置string
        /// </summary>
        public void PlayerPrefs_SetString(string key, string defaultValue)
        {
            //设置到缓存
            SetItemToCache(key, defaultValue);
        }

        /// <summary>
        /// get string
        /// </summary>
        public string PlayerPrefs_GetString(string key, string defaultValue = "")
        {
            //优先从缓存中获取
            if (_cache.TryGetValue(key, out var match))
            {
                return match.IsDelete ? defaultValue : match.Value as string;
            }

            SdkDebug.Log($"PlayerPrefs_GetString key:{key} defaultValue:{defaultValue}");
            var result = CallReturn("PlayerPrefs_GetString", new { key, value = defaultValue });
            return result;
        }

        /// <summary>
        /// get int
        /// </summary>
        public int PlayerPrefs_GetInt(string key, int defaultValue = 0)
        {
            //优先从缓存中获取
            if (_cache.TryGetValue(key, out var match))
            {
                return match.IsDelete ? defaultValue : (int)match.Value;
            }

            SdkDebug.Log($"PlayerPrefs_GetInt key:{key} defaultValue:{defaultValue}");
            var result = CallReturn("PlayerPrefs_GetInt", new { key, value = defaultValue });
            return int.Parse(result);
        }

        /// <summary>
        /// get float
        /// </summary>
        public float PlayerPrefs_GetFloat(string key, float defaultValue = 0f)
        {
            //优先从缓存中获取
            if (_cache.TryGetValue(key, out var match))
            {
                return match.IsDelete ? defaultValue : (float)match.Value;
            }

            SdkDebug.Log($"PlayerPrefs_GetFloat key:{key} defaultValue:{defaultValue}");
            var result = CallReturn("PlayerPrefs_GetFloat", new { key, value = defaultValue });
            return float.Parse(result);
        }

        /// <summary>
        /// 保存
        /// </summary>
        public void PlayerPrefs_Save()
        {
            SdkDebug.Log($"PlayerPrefs_Save...");
            //更新的keys
            var update = new List<StorageItem>();
            //删除的keys
            var remove = new List<string>();
            //将缓存的内容写到外部
            foreach (var pair in _cache)
            {
                var key = pair.Key;
                var value = pair.Value;
                if (value.IsDelete)
                {
                    remove.Add(key);
                }
                else
                {
                    update.Add(new StorageItem(key, value.Value));
                }
            }

            var sessionItem = new SessionItem("PlayerPrefs_Save", new { update, remove }, null);
            Call(sessionItem);
            //清空缓存
            _cache.Clear();
        }

        /// <summary>
        /// 删除所有key
        /// </summary>
        public void PlayerPrefs_DeleteAll()
        {
            SdkDebug.Log($"PlayerPrefs_DeleteAll...");
            //清理小游戏端
            var sessionItem = new SessionItem("PlayerPrefs_DeleteAll", new { }, null);
            Call(sessionItem);
            //请空缓存
            _cache.Clear();
        }

        /// <summary>
        /// 删除key
        /// </summary>
        public void PlayerPrefs_DeleteKey(string key)
        {
            RemoveItemFromCache(key);
        }

        /// <summary>
        /// 是否有key
        /// </summary>
        public bool PlayerPrefs_HasKey(string key)
        {
            //检查缓存
            if (_cache.TryGetValue(key, out var match))
            {
                SdkDebug.Log($"PlayerPrefs_HasKey,key:{key},从缓存中获取:{!match.IsDelete}");
                return !match.IsDelete;
            }

            //从小游戏端获取
            var result = CallReturn("PlayerPrefs_HasKey", new { key });
            SdkDebug.Log($"PlayerPrefs_HasKey,key:{key} result:{result}");
            return result == "1";
        }

        #endregion
    }
}