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

namespace TyphoonUnitySDK
{
    /// <summary>
    /// 抖音小游戏sdk
    /// </summary>
    [Preserve]
    public class DouyinSdk : BaseSdk
    {
        /*抖音小游戏admanager*/
        private StarkAdManager _adManager = null;

        /*游戏录制*/
        private StarkGameRecorder _recorder = null;

        //侧边栏api
        private StarkSideBar _starkSideBar = null;

        //上一次插页展示的时间
        private float _lastIntersTime;

        //展示过插页广告的标记
        private bool _showIntersFlag;

        //插页广告实例
        private StarkAdManager.InterstitialAd _interstitialAd;

        private bool _interstitialAdIsLoaded = false;

        //底部banner
        private DouyinBannerAd _bottomBanner;

        //顶部banner
        private DouyinBannerAd _topBanner;

        private bool _hasBannerId = false;
        private bool _hasIntersId = false;
        private bool _hasVideoOn = false;

        /*录制的视频路径*/
        private string _videoPath = "";

        /*在录制中*/
        private bool _isRecording = false;

        /*是否有录屏*/
        private bool _hasRecord = false;

        /*分享结果*/
        [NonSerialized] public Dictionary<string, object> ShareSuccessResult;


        public GameObject DouyinSdkMono;

        //缓存的onshow携带参数
        private Dictionary<string, object> _cacheOnShowParams = null;

        //是否支持侧边栏缓存标记
        private bool? _isSupportSideBarFlag = null;


        public override void OnCreate()
        {
            DouyinSdkMono = new GameObject("DouyinSdkMono");
            GameObject.DontDestroyOnLoad(DouyinSdkMono);
            _lastIntersTime = Time.unscaledTime;
            //初始化视频广告管理器
            if (CanIUse.GetStarkAdManager)
            {
                _hasBannerId = !string.IsNullOrEmpty(AppConfig.DouyinBannerId);
                _hasIntersId = !string.IsNullOrEmpty(AppConfig.DouyinIntersId);
                _hasVideoOn = !string.IsNullOrEmpty(AppConfig.DouyinVideoId);
                _adManager = StarkSDK.API.GetStarkAdManager();

                if (_hasIntersId)
                {
                    SdkDebug.Log("[DouyinSdk] 15秒后,加载插页广告");
                    SdkLite.Instance.WaitTo(15, LoadIntersAd);
                }

                if (_hasBannerId)
                {
                    SdkDebug.Log("[DouyinSdk] 初始化Banner条");
                    _bottomBanner = DouyinSdkMono.AddComponent<DouyinBannerAd>();
                    _bottomBanner.Initialize(BannerPosition.Bottom);

                    _topBanner = DouyinSdkMono.AddComponent<DouyinBannerAd>();
                    _topBanner.Initialize(BannerPosition.Top);
                }
            }

            if (CanIUse.GetStarkGameRecorder)
            {
                _recorder = StarkSDK.API.GetStarkGameRecorder();
            }

            if (CanIUse.GetStarkSideBarManager)
            {
                _starkSideBar = StarkSDK.API.GetStarkSideBarManager();
            }

            //订阅显示隐藏
            if (CanIUse.GetStarkAppLifeCycle)
            {
                StarkSDK.API.GetStarkAppLifeCycle().OnShowWithDict += OnShow;
                StarkSDK.API.GetStarkAppLifeCycle().OnHide += OnHide;
            }

            HttpGet("http://127.0.0.1:51824/home", (res) =>
            {
                // Debug.Log($"[DouyinSDK] LOG MODE RES：{res.ToXJson()}");
                if (res.StatusCode == 200 && res.DataString == "ok")
                {
                    Debug.Log("[DouyinSdk]开启动态调试");
                    SdkDebug.IsDebug = true;
                }
            }, (err) => { Debug.Log($"[DouyinSDK] LOG MODE ERR：{err}"); }, null, 3);
        }

        private void OnHide()
        {
            SdkDebug.Log($"[DouyinSdk] OnHide");
            SdkLite.InvokeOnHide();
        }

        private void OnShow(Dictionary<string, object> param)
        {
            SdkDebug.Log($"[DouyinSdk] OnShow:{param.ToXJson()}");
            _cacheOnShowParams = param;
            SdkLite.InvokeOnShow();
        }

        #region 初始化

        public override void InitSdk(Action success, Action<string> fail)
        {
            success?.Invoke();
        }

        #endregion

        #region 登录

        public override void Login(Action success, Action<string> fail)
        {
            //初始化侧边栏标记位
            InitializeSideBarFlag(() => { success?.Invoke(); });
        }

        #endregion

        #region 视频广告

        /*视频广告*/
        public override void ShowVideo(string scene, Action success, Action<string> fail)
        {
            SdkDebug.Log("[DouyinSdk] ShowVideo");
            if (_adManager == null)
            {
                fail?.Invoke("StarkAdManager not support");
                return;
            }

            if (!_hasVideoOn)
            {
                fail.Invoke("video id is null");
                return;
            }

            _adManager.ShowVideoAdWithId(AppConfig.DouyinVideoId, (complete) =>
            {
                SdkDebug.Log($"[DouyinSdk] ShowVideoAdWithId{complete}");
                if (complete)
                {
                    SdkDebug.Log($"[DouyinSdk] ShowVideoAdWithId success");
                    success?.Invoke();
                }
                else
                {
                    //广告未播放完毕
                    SdkDebug.Log($"[DouyinSdk] ShowVideoAdWithId fail");
                    fail.Invoke("no complete");
                }
            }, (code, err) =>
            {
                SdkDebug.Log($"[DouyinSdk] 视频广告播放失败  error code:{code} err:{err} ");
                //TODO//是否弹出错误信息
                fail.Invoke($"视频广告播放失败,错误码 : {code}");
            });
        }

        #endregion

        #region 插页广告

        /*加载插页广告*/
        private void LoadIntersAd()
        {
            if (_adManager == null)
            {
                return;
            }

            if (!_hasIntersId)
            {
                return;
            }

            _interstitialAdIsLoaded = false;
            _interstitialAd =
                _adManager.CreateInterstitialAd(AppConfig.DouyinIntersId,
                    (code, err) =>
                    {
                        SdkDebug.Log($"[DouyinSdk] LoadIntersAd error:{code} msg:{err}");
                        if (code == 1002)
                        {
                            SdkDebug.Log($"[DouyinSdk] 广告单元无效，停止加载！");
                        }
                        else
                        {
                            //5秒后重试
                            SdkLite.Instance.WaitTo(5, LoadIntersAd);
                        }
                    }, () =>
                    {
                        //加载完毕
                        SdkDebug.Log("[DouyinSdk] LoadIntersAd close");
                        //5秒后重试
                        SdkLite.Instance.WaitTo(1, LoadIntersAd);
                    }, () =>
                    {
                        //加载完毕
                        SdkDebug.Log("[DouyinSdk] Inters加载完毕");
                        _interstitialAdIsLoaded = true;
                    });
        }

        /*展示插页广告*/
        public override void ShowInters(string scene)
        {
            SdkDebug.Log("[DouyinSdk] ShowInters");
            if (_adManager == null)
            {
                SdkDebug.Log("[DouyinSdk] _adManager is null");
                return;
            }

            if (!_hasIntersId)
            {
                SdkDebug.Log("[DouyinSdk] inters id is null");
                return;
            }

            if (_interstitialAd == null || !_interstitialAdIsLoaded)
            {
                SdkDebug.Log("[DouyinSdk] _interstitialAd is null or not loaded");
                return;
            }

            var offset = Time.unscaledTime - _lastIntersTime;
            var cooldown = !_showIntersFlag ? 16 : 31;
            if (offset < cooldown)
            {
                SdkDebug.Log("[DouyinSdk] 广告最小冷却时间不满足平台要求，忽略广告调用");
                return;
            }

            _showIntersFlag = true;
            _lastIntersTime = Time.unscaledTime;
            _interstitialAdIsLoaded = false;
            _interstitialAd.Show();
            _interstitialAd = null;
        }

        #endregion

        #region Banner广告

        /*展示banner*/
        public override void ShowBanner(string scene, BannerPosition position)
        {
            if (!_hasBannerId)
            {
                SdkDebug.Log("[DouyinSdk] banner id is null");
                return;
            }

            switch (position)
            {
                case BannerPosition.Bottom:
                    _bottomBanner.SetState(true);
                    _topBanner.SetState(false);
                    break;
                case BannerPosition.Top:
                    _bottomBanner.SetState(false);
                    _topBanner.SetState(true);
                    break;
            }
        }

        /*隐藏banner*/
        public override void HideBanner(string scene)
        {
            if (!_hasBannerId)
            {
                SdkDebug.Log("[DouyinSdk] banner id is null");
                return;
            }

            _bottomBanner.SetState(false);
            _topBanner.SetState(false);
        }

        #endregion

        #region 录屏分享

        /*是否支持游戏录屏*/
        public override bool IsSupportGameRecord()
        {
            var flag = _recorder != null;
            SdkDebug.Log($"[DouyinSdk] CanRecordGame {flag}");
            return flag;
        }

        /// <summary>
        /// 开始录屏
        /// </summary>
        /// <param name="isRecordAudio">是否录制声音，默认为录制声音</param>
        /// <param name="maxRecordTimeSec">最大录制时长，单位 s。小于等于 0 则无限制。默认为10分钟</param>
        /// <param name="startCallback">视频录制开始回调</param>
        /// <param name="errorCallback">视频录制失败回调</param>
        /// <param name="onComplete">到达时间时自动执行,完成回调</param>
        public override void StartGameRecord(bool isRecordAudio = true, int maxRecordTimeSec = 600,
            Action onStart = null, Action<string> onError = null, Action<string> onComplete = null)
        {
            SdkDebug.Log("[DouyinSdk] StartRecordGame");
            if (_recorder == null)
            {
                onError?.Invoke("not support");
                return;
            }

            _videoPath = string.Empty;
            _hasRecord = false;
            _isRecording = _recorder.StartRecord(isRecordAudio, maxRecordTimeSec, () => onStart?.Invoke(),
                (code, msg) => onError?.Invoke($"code:{code},err:{msg}"), (videoPath) =>
                {
                    _videoPath = videoPath;
                    onComplete?.Invoke(videoPath);
                });
        }

        /// <summary>
        /// 停止录屏
        /// </summary>
        /// <param name="complete">视频录制完成回调</param>
        /// <param name="onError">视频录制失败回调</param>
        /// <param name="clips">停止后需要对视频进行裁剪的时间片段，如果为null或空列表，则不对视频进行裁剪</param>
        /// <param name="autoMerge">是否对视频裁剪片段进行自动合并</param>
        public override void StopGameRecord(Action<string> complete = null, Action<string> onError = null,
            List<TimeClip> clips = null,
            bool autoMerge = true)
        {
            SdkDebug.Log("[DouyinSdk] StopRecordGame");
            if (_recorder == null)
            {
                onError?.Invoke("not support");
                return;
            }

            //转成字节的类型
            List<StarkGameRecorder.TimeRange> ranges = null;
            if (clips != null)
            {
                ranges = new List<StarkGameRecorder.TimeRange>();
                foreach (var element in clips)
                {
                    ranges.Add(new StarkGameRecorder.TimeRange(element.Start, element.End));
                }
            }

            var succ = _recorder.StopRecord((videoPath) =>
                {
                    SdkDebug.Log($"[DouyinSdk] StopRecord success video path:{videoPath}");
                    _videoPath = videoPath;
                    complete?.Invoke(videoPath);
                },
                (code, msg) => onError?.Invoke($"code:{code},err:{msg}"), ranges, autoMerge);
            if (succ)
            {
                _hasRecord = true;
            }

            _isRecording = false;
        }


        /// <summary>
        /// 是否可分享录屏
        /// </summary>
        public override bool CanShareRecordGame()
        {
            if (_recorder == null)
            {
                SdkDebug.Log($"[DouyinSdk] CanShareRecordGame flag false, is not support");
                return false;
            }

            var flag = !string.IsNullOrEmpty(_videoPath) || _hasRecord;
            SdkDebug.Log($"[DouyinSdk] CanShareRecordGame flag:{flag},video path:{_videoPath},has record:{_hasRecord}");
            return flag;
        }


        /// <summary>
        /// 获取录屏时长，单位秒
        /// </summary>
        public override float GetGameRecordDuration()
        {
            return _recorder.GetRecordDuration() * 0.001f;
        }


        /// <summary>
        /// 分享录屏
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="topics">话题</param>
        /// <param name="success">成功回调</param>
        /// <param name="fail">失败回调</param>
        /// <param name="cancel">取消回调</param>
        public override void ShareRecordGame(string title, List<string> topics, Action success,
            Action<string> fail = null,
            Action cancel = null)
        {
            if (_recorder == null)
            {
                fail?.Invoke("not support");
                return;
            }

            _recorder.ShareVideoWithTitleTopics((successRes) =>
            {
                ShareSuccessResult = successRes;
                success?.Invoke();
            }, (err) => fail?.Invoke(err), () => cancel?.Invoke(), title, topics);
        }


        public override void ClearGameRecord()
        {
            SdkDebug.Log($"[DouyinSdk] ClearGameRecord");
            if (_recorder == null)
            {
                return;
            }

            _videoPath = string.Empty;
            _hasRecord = false;
        }

        #endregion

        #region 侧边栏

        //是否支持侧边栏
        public override bool IsSupportSideBar()
        {
            if (_isSupportSideBarFlag == null)
            {
                Debug.LogError("请登录完成后再调用该接口，IsSupportSideBar");
            }

            if (_isSupportSideBarFlag != null)
            {
                return _isSupportSideBarFlag.Value;
            }

            return false;
        }

        public override void CheckSideBarSupportFlag(Action success, Action<string> fail)
        {
            SdkDebug.Log("[DouyinSdk] IsSupportSideBar");
            if (_starkSideBar == null)
            {
                fail?.Invoke("不支持侧边栏API");
                return;
            }

            StarkSDK.API.GetStarkSideBarManager().CheckScene(StarkSideBar.SceneEnum.SideBar, b =>
                {
                    SdkDebug.Log($"[DouyinSdk] CheckScene SideBar :{b}");
                    if (b)
                    {
                        success?.Invoke();
                    }
                    else
                    {
                        fail?.Invoke("not support");
                    }
                }, () => { },
                (errCode, errMsg) => { fail?.Invoke($"error ! code:{errCode} msg:{errMsg}"); });
        }

        public override void NavigateToSideBar(Action success, Action<string> fail)
        {
            SdkDebug.Log("[DouyinSdk] NavigateToSideBar");
            if (_starkSideBar == null)
            {
                fail?.Invoke("不支持侧边栏API");
                return;
            }

            StarkSDK.API.GetStarkSideBarManager().NavigateToScene(StarkSideBar.SceneEnum.SideBar,
                () =>
                {
                    SdkDebug.Log("[DouyinSdk] NavigateToScene success");
                    success?.Invoke();
                }, () => { },
                (errCode, errMsg) =>
                {
                    SdkDebug.Log($"[DouyinSdk] NavigateToScene error {errCode} {errMsg}");
                    fail?.Invoke($"error,code:{errCode} msg:{errMsg}");
                });
        }

        public override bool IsEnterFromSideBar()
        {
            SdkDebug.Log("[DouyinSdk] IsEnterFromSideBar");
            if (_starkSideBar == null)
            {
                SdkDebug.Log("[DouyinSdk] 不支持侧边栏API");
                return false;
            }

            var launchFrom = StarkSDK.s_ContainerEnv.GetLaunchFrom();
            var location = StarkSDK.s_ContainerEnv.GetLocation();
            return launchFrom == "homepage" && location == "sidebar_card";
        }


        //尝试加载侧边栏标记位
        private void InitializeSideBarFlag(Action complete)
        {
            if (_isSupportSideBarFlag != null)
            {
                complete?.Invoke();
                return;
            }

            _isSupportSideBarFlag = false;
            CheckSideBarSupportFlag(() =>
            {
                _isSupportSideBarFlag = true;
                complete?.Invoke();
            }, (err) => { complete?.Invoke(); });
        }

        #endregion

        #region Toast

        public override void ShowToast(string message)
        {
            if (AppConfig.Channel == AppChannel.DouyinIOS)
            {
                StarkSDKSpace.StarkUIManager.ShowToast(message);
            }
            else
            {
                base.ShowToast(message);
            }
        }

        #endregion

        #region 事件上报

        public override void Track(string eventName, KvMap map)
        {
            SdkDebug.Log($"[DouyinSdk] Track [eventName]: {eventName} [map]: {map.ToXJson()}");
            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;
                }

                //浮点数
                if (value is float || value is double || value is decimal)
                {
                    output.Add(key, value);
                    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());
            }

            StarkSDK.API.ReportAnalytics(eventName, output);
        }

        #endregion
    }
}