using UnityEngine;
using System.Collections.Generic;
using System;
using FairyGUI;
using System.Linq;
using ET;
using YooAsset;
using System.Threading.Tasks;
namespace GFGGame
{
    public class ViewStructure
    {
        public string name;
        public object viewData;
        public IUIView iUIView;
    }
    /// 
    /// 视图管理类
    /// 管理视图的显示、隐藏
    /// 
    public class ViewManager
    {
        private static List _viewStack;
        private static Dictionary _viewDic;
        private static GComponent _bottomLayer;
        private static GComponent _topLayer;
        private static GComponent _guideLayer;
        private static GComponent _modalLayer;
        private static GComponent _alertLayer;
        private static GComponent _debugLayer;
        private static GComponent _floatLayer;
        private static Dictionary> _goBackDatas = new Dictionary>();
        public static void Init()
        {
            //设置CustomLoader
            UIObjectFactory.SetLoaderExtension(typeof(GFGGLoader));
            //通用资源,单独加,增加一次引用,不会被释放
            GFGUIPackage.AddPackage(ResPathUtil.GetUIPackagePath("Common"));
            GFGUIPackage.AddPackage(ResPathUtil.GetUIPackagePath("CommonGame"));
            GFGUIPackage.AddPackage(ResPathUtil.GetUIPackagePath("Main"));
            //await GFGUIPackage.AddPackageAsync(ResPathUtil.GetUIPackagePath("Common"));
            UIConfig.buttonSound = (NAudioClip)UIPackage.GetItemAsset("Common", "click");
            UIConfig.defaultFont = "FZKTJW--GB1-0";
            //默认关闭点击窗口移至顶层的功能,不可打开,如哪个界面需要在界面中单独设置
            UIConfig.bringWindowToFrontOnClick = false;
            _viewDic = new Dictionary();
            _viewStack = new List();
            //初始化视图层容器
            _bottomLayer = CreateLayer("BottomLayer");
            //_bottomLayer.sortingOrder = ConstSortingOrder.Bottom;
            _topLayer = CreateLayer("TopLayer");
            _topLayer.sortingOrder = ConstSortingOrder.TOP;
            _guideLayer = CreateLayer("GuideLayer");
            _guideLayer.sortingOrder = ConstSortingOrder.Guide;
            _modalLayer = CreateLayer("ModalLayer");
            _modalLayer.sortingOrder = ConstSortingOrder.Modal;
            _alertLayer = CreateLayer("AlertLayer");
            _alertLayer.sortingOrder = ConstSortingOrder.Alert;
            //debug层
            _debugLayer = CreateLayer("DebugLayer");
            _debugLayer.sortingOrder = ConstSortingOrder.Debug;
            _floatLayer = CreateLayer("FloatLayer");
            _floatLayer.sortingOrder = ConstSortingOrder.Float;
            SetMaskAlpha(0.6f);
        }
        public static void AddChildToBottomLayer(GObject gObject)
        {
            _bottomLayer.AddChild(gObject);
        }
        public static void AddChildToTopLayer(GObject gObject)
        {
            _topLayer.AddChild(gObject);
        }
        public static void AddChildToGuideLayer(GObject gObject)
        {
            _guideLayer.AddChild(gObject);
        }
        public static void AddChildToModalLayer(GObject gObject)
        {
            _modalLayer.AddChild(gObject);
        }
        public static void AddChildToAlertLayer(GObject gObject)
        {
            _alertLayer.AddChild(gObject);
        }
        public static void AddChildToDebugLayer(GObject gObject)
        {
            _debugLayer.AddChild(gObject);
        }
        public static void AddChildToFloatLayer(GObject gObject)
        {
            _floatLayer.AddChild(gObject);
        }
        /// 
        /// 显示一个视图
        /// 
        /// 要显示的视图名称
        /// 要传递给视图的参数
        /// 从该视图返回的视图信息
        /// 是否关闭其他视图
        public static bool Show(string fullViewName, object viewData = null, object[] goBackParams = null, bool hideOthers = false, bool resetGobackParams = false)
        {
            string name = GetName(fullViewName);
            if (!GameGlobal.skipCheckOpen && !FunctionOpenDataManager.Instance.CheckIsFunOpenById(name))
            {
                return false;
            }
            if (hideOthers)
            {
                for (int i = _viewStack.Count - 1; i >= 0; i--)
                {
                    if (_viewStack[i].name != "MainUIView")
                        _viewStack.RemoveAt(i);
                }
                HideAllView(name);
            }
            IUIView obj = null;
            if (_viewDic.ContainsKey(name))
            {
                obj = _viewDic[name];
            }
            else
            {
                obj = CreateViewInstance(fullViewName) as IUIView;
                obj.viewName = name;
                _viewDic.Add(name, obj);
            }
            if (obj != null)
            {
                IUIView view = (IUIView)obj;
                view.viewData = viewData;
                if (!view.isShowing)
                {
                    view.Show();
                }
                else
                {
                    view.Refresh();
                }
                LogUtil.LogDev("当前打开:" + name);
            }
            if (name == "MainUIView")
            {
                _viewStack.Clear();
            }
            //判断是否需要保存界面数据, 会帮助关闭上一个保存界面
            if (obj.isReturnView && (_viewStack.Count <= 0 || (_viewStack.Count > 0 && _viewStack[_viewStack.Count - 1].name != name)))
            {
                ViewStructure viewStructure = new ViewStructure();
                viewStructure.name = name;
                viewStructure.viewData = viewData;
                viewStructure.iUIView = obj;
                _viewStack.Add(viewStructure);
                if (_viewStack.Count > 1)
                    _viewStack[_viewStack.Count - 2].iUIView.Hide();
            }
            return true;
        }
        public static bool isViewOpen(string fullViewName)
        {
            string name = GetName(fullViewName);
            IUIView obj = null;
            if (_viewDic.ContainsKey(name))
            {
                obj = _viewDic[name];
                if (obj != null)
                {
                    IUIView view = (IUIView)obj;
                    if (view.isShowing) return true;
                }
            }
            return false;
        }
        public static bool Show(object viewData = null, object[] goBackParams = null, bool hideOthers = false, bool resetGobackParams = false) where T : class, new()
        {
            // string[] names = typeof(T).FullName.Split('.');
            // string viewName = names[names.Length - 1];
            //string name = GetName(typeof(T).FullName);
            return ViewManager.Show(typeof(T).FullName, viewData, null, hideOthers);
        }
        public static void HideWin(string viewName)
        {
            if (_viewStack.Count > 1) {
                ViewStructure viewStructure = _viewStack[_viewStack.Count - 1];
                if (viewStructure.iUIView.isReturnView && viewStructure.name == viewName)
                {
                    _viewStack.RemoveAt(_viewStack.Count - 1);
                    if (_viewStack.Count >= 1)
                    {
                        viewStructure = _viewStack[_viewStack.Count - 1];
                        ViewManager.Show($"GFGGame.{viewStructure.name}", viewStructure.viewData);
                        foreach (var objName in _viewDic.Keys)
                        {
                            if (objName != viewStructure.name)
                            {
                                IUIView view = (IUIView)_viewDic[objName];
                                if (view.isShowing)
                                {
                                    view.Show();
                                }
                            }
                        }
                    }
                }
            }
        }
        public static void Hide(string fullViewName)
        {
            string name = GetName(fullViewName);
            if (!_viewDic.ContainsKey(name))
            {
                return;
            }
            object obj = _viewDic[name];
            if (obj != null)
            {
                IUIView view = (IUIView)obj;
                view.Hide();
                LogUtil.LogDev("当前关闭:" + name);
            }
        }
        public static void Hide()
        {
            //string name = GetName(typeof(T).FullName);
            Hide(typeof(T).FullName);
        }
        public static void GoBackFrom(string fullViewName, bool hideOther = true)
        {
            string name = GetName(fullViewName);
            ViewManager.Hide(name);
            foreach (var info in _viewDic.Keys)
            {
                IUIView objIsShowing = _viewDic[info];
                if (objIsShowing != null && objIsShowing.isShowing)
                {
                    return;
                }
            }
            MainDataManager.Instance.ViewType = 0;
            ViewManager.Show(null, null, true);
        }
        public static object[] GetGoBackDatas(string fullViewName)
        {
            //string name = GetName(fullViewName);
            object[] value = null;
            //if (_goBackDatas.ContainsKey(name) && _goBackDatas[name].Count > 0)
            //{
            //    value = _goBackDatas[name][_goBackDatas[name].Count - 1];
            //}
            return value;
        }
        public static IUIView GetUIView(string viewName)
        {
            IUIView obj = _viewDic[viewName];
            if (obj != null && obj.isShowing)
            {
                return obj as IUIView;
            }
            return null;
        }
        public static void ClearUIView(string viewName)
        {
            if (!string.IsNullOrEmpty(viewName) && _viewDic.ContainsKey(viewName))
            {
                if (_viewDic[viewName] != null && !_viewDic[viewName].isShowing)
                {
                    // _viewDic[viewName] = null;
                    _viewDic.Remove(viewName);
                }
            }
        }
        public static void HideAllView(string excludeViewName = null)
        {
            for (int i = _viewDic.Keys.Count - 1; i >= 0; i--)//不用foreach是因为:循环过程中可能会触发dispose,导致_viewDic.Keys变化,最终报错
            {
                int index = i > _viewDic.Keys.Count - 1 ? _viewDic.Keys.Count - 1 : i;//直接去最后一个,不用i是因为关闭一个界面可能会连带关闭其他界面,最终i比_viewDic.Keys.Count大而报错
                KeyValuePair kv = _viewDic.ElementAt(index);
                if (kv.Key != excludeViewName)
                {
                    if (kv.Key == typeof(FunctionOpenView).Name) continue;//功能开启界面不能强制关闭
                    Hide(kv.Key);
                }
            }
            // _viewDic.Clear();
            // foreach (string viewName in _viewDic.Keys)
            // {
            //     if (viewName != excludeViewName)
            //     {
            //         if (viewName == typeof(FunctionOpenView).Name) continue;//功能开启界面不能强制关闭
            //         Hide(viewName);
            //     }
            // }
        }
        public static void CheckDispose()
        {
            for (int i = _viewDic.Keys.Count - 1; i >= 0; i--)//不用foreach是因为:循环过程中可能会触发dispose,导致_viewDic.Keys变化,最终报错
            {
                int index = i > _viewDic.Keys.Count - 1 ? _viewDic.Keys.Count - 1 : i;//直接去最后一个,不用i是因为关闭一个界面可能会连带关闭其他界面,最终i比_viewDic.Keys.Count大而报错
                KeyValuePair kv = _viewDic.ElementAt(index);
                if (kv.Value.isShowing == true) continue;
                // if (kv.Value.packageName == ResPathUtil.GetUIPackagePath("CommonGame") || kv.Value.packageName == ResPathUtil.GetUIPackagePath("Common") || kv.Value.packageName == ResPathUtil.GetUIPackagePath("Main")) return;//这几个包不释放
                if(_viewDic.Keys.Count <= 10) return;  //打开界面小于10个就不销毁了
                long currentTime = TimeHelper.ClientNowSeconds();
                long closeTime = kv.Value.closeTime;
                if (closeTime > 0 && currentTime - closeTime >= TimeUtil.SECOND_PER_MUNITE * 1)
                {
                    kv.Value.closeTime = 0;
                    kv.Value.Dispose();
                }
            }
        }
        private static object CreateViewInstance(string name)
        {
            //LogUtil.LogFormatDev("CreateViewInstance {0}", name);
            Type type = Type.GetType(name);
            if (type != null)
            {
                return Activator.CreateInstance(type);
            }
            return null;
        }
        private static GComponent CreateLayer(string name)
        {
            GComponent layer = new GComponent();
            layer.name = name;
            GRoot.inst.AddChild(layer);
            layer.SetSize(GRoot.inst.size.x, GRoot.inst.size.y);
            layer.AddRelation(GRoot.inst, RelationType.Size);
            return layer;
        }
        public static bool CheckIsTopView(GComponent viewCom)
        {
            if (ViewManager.isViewOpen(typeof(GuideView).Name)) return false;
            if (viewCom.parent != null)
            {
                int index = viewCom.parent.GetChildIndex(viewCom);
                if (index == viewCom.parent.numChildren - 1 && GRoot.inst.GetTopWindow() == null)
                {
                    return true;
                }
            }
            if (GRoot.inst.GetTopWindow() == viewCom)
            {
                return true;
            }
            return false;
        }
        public static string GetName(string fullName)
        {
            string[] names = fullName.Split('.');
            string name = names[names.Length - 1];
            return name;
        }
        public static void SetMaskAlpha(float alpha)
        {
            GRoot.inst.modalLayer.alpha = alpha;
        }
        /// 
        /// 任务界面跳转
        /// 
        /// 
        public static void JumpToView(string jumpId, object[] param, object[] goBackDatas, bool hideOther = false, Action onSuccess = null)
        {
            switch (jumpId)
            {
                case nameof(LeagueAnswerView):
                    if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
                    {
                        ViewManager.Show(null, goBackDatas, hideOther);
                        ViewManager.Show($"GFGGame.{jumpId}");
                    }
                    else
                    {
                        if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
                        ViewManager.Show(null, goBackDatas, hideOther, true);
                    }
                    break;
                case nameof(LeagueView):
                    if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
                    if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
                    {
                        ViewManager.Show(null, goBackDatas, hideOther);
                    }
                    else
                    {
                        ViewManager.Show(null, goBackDatas, hideOther, true);
                    }
                    break;
                case nameof(StoreView):
                    ViewManager.Show(param, goBackDatas, hideOther);
                    break;
                case nameof(StoryChapterListView):
                    ViewManager.Show($"GFGGame.{jumpId}", param, goBackDatas, hideOther, true);
                    break;
                case nameof(StoryChapterView):
                    ViewManager.Show(param[0], goBackDatas, hideOther);
                    break;
                case nameof(FirstChargeBonusView):
                    ViewManager.Show(param, goBackDatas, false);
                    break;
                case nameof(ClothingSyntheticView):
                    ViewManager.Show(param, goBackDatas, false);
                    break;
                case nameof(LuckyBoxView):
                    if(param.Length > 0)
                        ViewManager.Show(param[0], goBackDatas, false);
                    else
                        ViewManager.Show(null, goBackDatas, false);
                    break;
                default:
                    ViewManager.Show($"GFGGame.{jumpId}", null, goBackDatas, hideOther, true);
                    break;
            }
            onSuccess?.Invoke();
        }
    }
}