using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Scripting;

namespace TyphoonUnitySDK
{
    [Preserve]
    public class WxMiniSdk : BaseSdk
    {
        [Serializable]
        public class HttpPostRsp
        {
            public string ret;
            public object data;
            public Dictionary<string, string> header;
            public long statusCode;
        }


        public const string CALL_BACK_GAME_OBJECT_NAME = "TYPHOON_SDK_CALL_BACK";
        public WxMiniSdkCallBack CallBack;

        //缓存的sessionId
        private long _showVideoSessionId = -1;

        public override void OnCreate()
        {
            //创建回调对象
            CallBack = new GameObject(CALL_BACK_GAME_OBJECT_NAME).AddComponent<WxMiniSdkCallBack>();
            CallBack.Initialize();
            GameObject.DontDestroyOnLoad(CallBack.gameObject);
        }

        #region 初始化SDK

        /*初始化sdk*/
        public override void InitSdk(Action success, Action<string> fail)
        {
            SdkDebug.Log("[WxMiniSdk] InitSdk");
            var session = new SessionItem("initSdk", null, (res) =>
            {
                if (res == "ok")
                {
                    SdkDebug.Log("[WxMiniSdk] InitSdk success");
                    success?.Invoke();
                }
                else
                {
                    SdkDebug.Log($"[WxMiniSdk] InitSdk fail : {res}");
                    //TODO//输出错误信息
                    fail?.Invoke(res);
                }
            });
            UnityToJs.Call(session);
        }

        #endregion

        #region 登录

        /*登录*/
        public override void Login(Action success, Action<string> fail)
        {
            SdkDebug.Log("[WxMiniSdk] Login");
            var session = new SessionItem("login", null, (res) =>
            {
                if (res == "ok")
                {
                    SdkDebug.Log("[WxMiniSdk] Login success");
                    success?.Invoke();
                }
                else
                {
                    SdkDebug.Log($"[WxMiniSdk] Login fail : {res}");
                    fail.Invoke(res);
                }
            });
            UnityToJs.Call(session);
        }

        #endregion

        #region banner

        /*展示Banner*/
        public override void ShowBanner(string scene, BannerPosition position)
        {
            //0是下banner，1是上banner
            UnityToJs.Call("showBanner", new { scene, pos = (int)position });
        }

        /*隐藏banner*/
        public override void HideBanner(string scene)
        {
            UnityToJs.Call("hideBanner", new { scene });
        }

        #endregion

        #region 插页广告

        public override void ShowInters(string scene)
        {
            SdkDebug.Log("[WxMiniSdk] ShowInters,scene:{scene}");
            UnityToJs.Call("showInters", new { scene });
        }

        #endregion

        #region 视频广告

        /*视频广告flag*/
        public override bool GetVideoFlag()
        {
            SdkDebug.Log("[WxMiniSdk] GetVideoFlag");
            var flag = UnityToJs.CallReturn("getVideoFlag", null) == "1";
            SdkDebug.Log("[WxMiniSdk] GetVideoFlag:{flag}");
            return flag;
        }

        /*播放视频广告*/
        public override void ShowVideo(string scene, Action success, Action<string> fail)
        {
            SdkDebug.Log("[WxMiniSdk] ShowVideo,scene:{scene}");
            SessionItem.ClearSession(_showVideoSessionId);
            var session = new SessionItem("showVideo", new { scene }, (res) =>
            {
                if (res == "ok")
                {
                    success?.Invoke();
                }
                else
                {
                    fail?.Invoke(res);
                }
            });
            _showVideoSessionId = session.SessionId;
            UnityToJs.Call(session);
        }

        #endregion

        #region Toast

        public override void ShowToast(string message)
        {
            SdkDebug.Log("[WxMiniSdk] ShowToast");
            var session = new SessionItem("showToast", new { message, duration = 1 }, null);
            UnityToJs.Call(session);
        }

        #endregion

        #region 事件上报

        public override void Track(string eventName, KvMap map)
        {
            SdkDebug.Log("[WxMiniSdk] Track");
            var output = new Dictionary<string, object>();
            //二次处理数据
            foreach (var pair in map)
            {
                var key = pair.Key;
                var value = pair.Value;
                //无值，默认取整数1
                if (value == null)
                {
                    output.Add(key, 1);
                    continue;
                }

                //如果是基础类型
                if (value is bool)
                {
                    //如果是bool类型
                    output.Add(key, (bool)value ? 1 : 0);
                    continue;
                }

                //浮点数,由于微信不支持小数，放大10000倍,取整数
                if (value is float || value is double || value is decimal)
                {
                    output.Add(key, (long)(double.Parse(value.ToString()) * 10000));
                    continue;
                }

                //整数
                if (value is int || value is long || value is short || value is ushort || value is uint ||
                    value is ulong)
                {
                    output.Add(key, value);
                    continue;
                }

                //其它类型
                output.Add(key, value.ToString());
            }

            var session = new SessionItem("track", new { eventName, eventData = output }, null);
            UnityToJs.Call(session);
        }

        #endregion

        #region HTTP 请求

        public override void HttpPost(string url, string data, Action<HttpPostSuccessResult> success,
            Action<string> fail, Dictionary<string, string> header = null, int timeOut = 60)
        {
            SdkDebug.Log($"[WxMiniSdk] HttpPost url:{url},data:{data} header:{header} timeOut:{timeOut}");
            var session = new SessionItem("httpPost", new { url, data, header, timeOut }, (res) =>
            {
                SdkDebug.Log($"[WxMiniSdk] HttpPost响应结果： {res} [请求参数]：url:{url} data:{data}");
                try
                {
                    var rsp = res.ToXObject<HttpPostRsp>();
                    if (rsp.ret == "ok")
                    {
                        SdkDebug.Log($"[WxMiniSdk] 响应成功");
                        success?.Invoke(new HttpPostSuccessResult(rsp.data, rsp.header, rsp.statusCode));
                    }
                    else
                    {
                        SdkDebug.Log($"[WxMiniSdk] 响应失败");
                        //触发失败回调
                        fail?.Invoke(rsp.ret);
                    }
                }
                catch (Exception e)
                {
                    fail?.Invoke($"解析参数失败:{res}");
                }
            });
            UnityToJs.Call(session);
        }

        public override void HttpGet(string url, Action<HttpGetSuccessResult> success, Action<string> fail,
            Dictionary<string, string> header, int timeOut = 60)
        {
            SdkDebug.Log($"[WxMiniSdk] HttpGet url:{url},header:{header} timeOut:{timeOut}");
            var session = new SessionItem("httpGet", new { url, header, timeOut }, (res) =>
            {
                SdkDebug.Log($"[WxMiniSdk] HttpGet 响应结果： {res} [请求参数]：url:{url} ");
                try
                {
                    var rsp = res.ToXObject<HttpPostRsp>();
                    if (rsp.ret == "ok")
                    {
                        SdkDebug.Log($"[WxMiniSdk] 响应成功");
                        success?.Invoke(new HttpGetSuccessResult(rsp.data, rsp.header, rsp.statusCode));
                    }
                    else
                    {
                        SdkDebug.Log($"[WxMiniSdk] 响应失败");
                        //触发失败回调
                        fail?.Invoke(rsp.ret);
                    }
                }
                catch (Exception e)
                {
                    fail?.Invoke($"解析参数失败:{res}");
                }
            });
            UnityToJs.Call(session);
        }

        #endregion
    }
}