using System.Collections.Generic;
using System;
using FairyGUI;
using System.Linq;
using ET;
namespace GFGGame
{
    public class ViewStructure
    {
        public string name;
        public object viewData;
        public IUIView iUIView;
        public bool backRefresh;
    }
    /// 
    /// 视图管理类
    /// 管理视图的显示、隐藏
    /// 
    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 bool _nowHideOthers = false;     //正在关闭所有界面的循环中
        private static Dictionary> _goBackDatas = new Dictionary>();
       
        public static void Clear()
        {
            _viewStack.Clear();
        }
        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");
            //统一修改文字字体需要填写路径 ResIn/Font/FZKTJW--GB1-0
            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 = ConstViewLayerSortingOrder.TOP;
            _guideLayer = CreateLayer("GuideLayer");
            _guideLayer.sortingOrder = ConstViewLayerSortingOrder.Guide;
            _modalLayer = CreateLayer("ModalLayer");
            _modalLayer.sortingOrder = ConstViewLayerSortingOrder.Modal;
            _alertLayer = CreateLayer("AlertLayer");
            _alertLayer.sortingOrder = ConstViewLayerSortingOrder.Alert;
            //debug层
            _debugLayer = CreateLayer("DebugLayer");
            _debugLayer.sortingOrder = ConstViewLayerSortingOrder.Debug;
            _floatLayer = CreateLayer("FloatLayer");
            _floatLayer.sortingOrder = ConstViewLayerSortingOrder.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, bool hideOthers = false, bool backRefresh = true,bool isHideToShow = false)
        {
            string name = GetName(fullViewName);
            if (!GameGlobal.skipCheckOpen && !FunctionOpenDataManager.Instance.CheckIsFunOpenById(name))
            {
                return false;
            }
            if (hideOthers)
            {
                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)
                {
                    if (isHideToShow && _viewStack.Count > 0)
                        view.backRefresh = _viewStack[_viewStack.Count - 1].backRefresh;
                    else
                        view.backRefresh = true;
                    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)))
            {
                //保存上一个界面是否需要返回刷新
                if (!isHideToShow && _viewStack.Count > 1)
                    _viewStack[_viewStack.Count - 1].backRefresh = backRefresh;
               
                ViewStructure viewStructure = new ViewStructure();
                viewStructure.name = name;
                viewStructure.viewData = viewData;
                viewStructure.iUIView = obj;
                _viewStack.Add(viewStructure);
                if (_viewStack.Count > 1 && !hideOthers) {
                    _viewStack[_viewStack.Count - 2].iUIView.Hide();
                }
            }
            return true;
        }
        //
        /// 
        /// 界面可返回栈里的跳转
        /// 
        /// 跳转到界面缓存栈里的某个界面,使用这个参数时写在打开下一个界面后
        /// 删除队列中的倒数几个,较灵活应对更多种情况,可自由控制
        public static void DeleteViewStackCountDown(string viewName, int count = 0)
        {
            if (viewName != null && viewName != "")
            {
                for (int i = _viewStack.Count - 2; i > 0; i--)
                {
                    ViewStructure viewStructure = _viewStack[i];
                    if (viewStructure.name == viewName)
                        break;
                    _viewStack.RemoveAt(i);
                }
                return;
            }
            for (int i = 0; i < count; i++) {
                if (_viewStack.Count <= 1)
                    break;
                _viewStack.RemoveAt(_viewStack.Count-1);
            }
        }
        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, bool hideOthers = false, bool backRefresh = true) 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, hideOthers, backRefresh);
        }
        public static void HideWin(string viewName)
        {
            if (_nowHideOthers)
                return;
            
            if (_viewStack.Count >= 1)
            {
                bool hasShowingView = false;
                bool needShowNextView = false;
                bool backRefresh = true;
                foreach (var info in _viewDic.Keys)
                {
                    IUIView objIsShowing = _viewDic[info];
                    if (objIsShowing != null && objIsShowing.isShowing)
                    {
                        hasShowingView = true;
                        break;
                    }
                }
                ViewStructure viewStructure = _viewStack[_viewStack.Count - 1];
                if (_viewStack.Count == 1)
                {
                    //没有界面显示了,栈被清除剩1个的时候,做保底
                    if (!hasShowingView)
                        needShowNextView = true;
                }
                else { 
                    if (!hasShowingView || (viewStructure.iUIView.isReturnView && viewStructure.name == viewName))
                    {
                        //关闭自己,在队列里去除
                        if (viewStructure.iUIView.isReturnView && viewStructure.name == viewName) {
                            backRefresh = viewStructure.backRefresh;
                            _viewStack.RemoveAt(_viewStack.Count - 1);
                        }
                        if (_viewStack.Count >= 1)
                            needShowNextView = true;
                    }
                }
                if (needShowNextView) { 
                    viewStructure = _viewStack[_viewStack.Count - 1];
                    ViewManager.Show($"GFGGame.{viewStructure.name}", viewStructure.viewData, false, backRefresh,  true);
                    //重新打开小弹窗
                    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, 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)
        {
            if (_viewDic.ContainsKey(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;//功能开启界面不能强制关闭
                    _nowHideOthers = true;
                    Hide(kv.Key);
                }
            }
            _nowHideOthers = false;
            // _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, bool hideOther = false, bool backRefresh = true, Action onSuccess = null)
        {
            switch (jumpId)
            {
                case nameof(LeagueAnswerView):
                    if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
                    {
                        ViewManager.Show(null, hideOther, backRefresh);
                        ViewManager.Show($"GFGGame.{jumpId}");
                    }
                    else
                    {
                        if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
                        ViewManager.Show(null, hideOther, backRefresh);
                    }
                    break;
                case nameof(LeagueView):
                    if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
                    if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
                    {
                        ViewManager.Show(null, hideOther, backRefresh);
                    }
                    else
                    {
                        ViewManager.Show(null, hideOther, backRefresh);
                    }
                    break;
                case nameof(StoreView):
                    ViewManager.Show(param, hideOther, backRefresh);
                    break;
                case nameof(StoryChapterListView):
                    ViewManager.Show($"GFGGame.{jumpId}", param, hideOther, backRefresh);
                    break;
                case nameof(StoryChapterView):
                    ViewManager.Show(param[0], hideOther, backRefresh);
                    break;
                case nameof(FirstChargeBonusView):
                    ViewManager.Show(param, false, backRefresh);
                    break;
                case nameof(ClothingSyntheticView):
                    ViewManager.Show(param, hideOther, backRefresh);
                    break;
                case nameof(LuckyBoxView):
                    if(param.Length > 0)
                        ViewManager.Show(param[0], hideOther, backRefresh);
                    else
                        ViewManager.Show(null, hideOther, backRefresh);
                    break;
                default:
                    ViewManager.Show($"GFGGame.{jumpId}", null, hideOther, backRefresh);
                    break;
            }
            onSuccess?.Invoke();
        }
    }
}