/// <summary>
    /// Create a UI
    /// </summary>
    /// <param name="p_type">UI category: fullscreen, window, popup, etc</param>
    /// <param name="p_name">name you defined</param>
    /// <param name="p_mediatorType"></param>
    /// <param name="p_bundlePath">prefab to instantiate</param>
    /// <param name="p_viewInitCallBack"></param>
    /// <param name="p_viewRefreshCallBack"></param>
    /// <param name="p_allocateDepth">allocate several panel depth to ui</param>
    /// <param name="p_viewName"></param>
    /// <param name="isShowAnimation"></param>
    private void CreateUI(UIItemConfig p_config, DelegateHelper.TableDelegate p_viewInitCallBack, DelegateHelper.TableDelegate p_viewRefreshCallBack = null, bool isShowAnimation = true)
    {
        try
        {
            if (!m_UICategoryMap.ContainsKey(p_config.Type))
            {
                throw new KeyNotFoundException(string.Format("Key: {0} not found in UI Category.", p_config.Type));
            }

            if (p_config.BundleName == null)
            {
                throw new Exception("Cannot create UI cause no res provided.");
            }

            Game.StartCoroutine(GameAssets.LoadAssetAsync <GameObject>(p_config.BundleName, p_config.AssetName,
                                                                       (prefab) =>
            {
                CreateUIInternal(p_config, prefab, p_viewInitCallBack,
                                 p_viewRefreshCallBack, isShowAnimation);
            }));
            GameAssets.AddBundleRef(p_config.BundleName);
        }
        catch (Exception e)
        {
            LogModule.ErrorLog("Exception in create UI, {0}\n{1}", e.Message, e.StackTrace);
            return;
        }
    }
    /// <summary>
    /// Open a UI, will create one if no cache exist
    /// </summary>
    /// <param name="p_type">UI category: fullscreen, window, popup, etc</param>
    /// <param name="p_name">name you defined</param>
    /// <param name="p_viewRefreshCallBack"></param>
    /// <param name="isShowAnimation"></param>
    private void ExeAfterOpenUI(UIItemConfig p_config, DelegateHelper.TableDelegate p_viewRefreshCallBack = null, bool isShowAnimation = true)
    {
        try
        {
            switch (m_uiCategoryConfigMap[p_config.Type].MultiPolicy)
            {
            case "Single":
            {
                foreach (var item in m_UICategoryMap[p_config.Type].UIItemList.Where(item => item.Name != p_config.Name))
                {
                    CloseUI(item.Name);
                }
                break;
            }

            case "Overlay":
            {
                break;
            }

            default:
            {
                throw new Exception(string.Format("MultiPolicy: {0} not defined.", m_uiCategoryConfigMap[p_config.Type].MultiPolicy));
            }
            }

            Utils.StandardizeObject(m_UIItemMap[p_config.Name].RootObject);
            m_UIItemMap[p_config.Name].RootObject.SetActive(true);
            m_UIItemMap[p_config.Name].IsShowing = true;

            if (isShowAnimation)
            {
                m_UIItemMap[p_config.Name].ViewBase.OnOpen();
            }
            //Refresh
            else
            {
                if (p_viewRefreshCallBack != null && m_UIItemMap[p_config.Name].View != null)
                {
                    m_UIItemMap[p_config.Name].ViewBase.OnOpenUIComplete += () =>
                    {
                        p_viewRefreshCallBack(m_UIItemMap[p_config.Name].View);
                    };
                }
            }
        }
        catch (Exception e)
        {
            LogModule.ErrorLog("Exception in exe after open UI, {0}\n{1}", e.Message, e.StackTrace);
            return;
        }
    }
    /// <summary>
    /// Open a UI, will create one if no cache exist
    /// </summary>
    /// <param name="p_type">UI category: fullscreen, window, popup, etc</param>
    /// <param name="p_name">name you defined</param>
    /// <param name="p_mediatorType"></param>
    /// <param name="p_bundlePath">prefab to instantiate</param>
    /// <param name="p_viewInitCallBack"></param>
    /// <param name="p_viewRefreshCallBack"></param>
    /// <param name="p_allocateDepth">allocate several panel depth to ui</param>
    /// <param name="p_viewName"></param>
    /// <param name="isShowAnimation"></param>
    public bool OpenUIInternal(UIItemConfig p_config, DelegateHelper.TableDelegate p_viewInitCallBack = null, DelegateHelper.TableDelegate p_viewRefreshCallBack = null, bool isShowAnimation = true)
    {
        try
        {
            if (m_UIItemMap.ContainsKey(p_config.Name) && m_UIItemMap[p_config.Name].IsShowing)
            {
                LogModule.WarningLog("Cancel open {0} UI cause already in showing.", p_config.Name);
                //Execute refresh without animation.
                ExeAfterOpenUI(p_config, p_viewRefreshCallBack, false);

                return(false);
            }

            if (!m_UICategoryMap[p_config.Type].CanOpenUI)
            {
                m_UICategoryMap[p_config.Type].AddToToShowList(new UICategory.ToShowConfig()
                {
                    ItemConfig      = p_config,
                    ViewDelegate    = p_viewInitCallBack,
                    RefreshDelegate = p_viewRefreshCallBack,
                    IsShowAnim      = isShowAnimation
                });
                return(false);
            }

            if (!m_UIItemMap.ContainsKey(p_config.Name))
            {
                CreateUI(p_config, p_viewInitCallBack, p_viewRefreshCallBack, isShowAnimation);
            }
            else
            {
                m_UICategoryMap[p_config.Type].CheckOpenDepth(p_config.Name);

                ExeAfterOpenUI(p_config, p_viewRefreshCallBack, isShowAnimation);
            }

            return(true);
        }
        catch (Exception e)
        {
            LogModule.ErrorLog("Exception in open UI internal, {0}\n{1}", e.Message, e.StackTrace);
            return(false);
        }
    }
    static int OpenUIInternal(IntPtr L)
    {
        try
        {
            ToLua.CheckArgsCount(L, 5);
            UIManager    obj  = (UIManager)ToLua.CheckObject(L, 1, typeof(UIManager));
            UIItemConfig arg0 = (UIItemConfig)ToLua.CheckObject(L, 2, typeof(UIItemConfig));
            DelegateHelper.TableDelegate arg1 = null;
            LuaTypes funcType3 = LuaDLL.lua_type(L, 3);

            if (funcType3 != LuaTypes.LUA_TFUNCTION)
            {
                arg1 = (DelegateHelper.TableDelegate)ToLua.CheckObject(L, 3, typeof(DelegateHelper.TableDelegate));
            }
            else
            {
                LuaFunction func = ToLua.ToLuaFunction(L, 3);
                arg1 = DelegateFactory.CreateDelegate(typeof(DelegateHelper.TableDelegate), func) as DelegateHelper.TableDelegate;
            }

            DelegateHelper.TableDelegate arg2 = null;
            LuaTypes funcType4 = LuaDLL.lua_type(L, 4);

            if (funcType4 != LuaTypes.LUA_TFUNCTION)
            {
                arg2 = (DelegateHelper.TableDelegate)ToLua.CheckObject(L, 4, typeof(DelegateHelper.TableDelegate));
            }
            else
            {
                LuaFunction func = ToLua.ToLuaFunction(L, 4);
                arg2 = DelegateFactory.CreateDelegate(typeof(DelegateHelper.TableDelegate), func) as DelegateHelper.TableDelegate;
            }

            bool arg3 = LuaDLL.luaL_checkboolean(L, 5);
            bool o    = obj.OpenUIInternal(arg0, arg1, arg2, arg3);
            LuaDLL.lua_pushboolean(L, o);
            return(1);
        }
        catch (Exception e)
        {
            return(LuaDLL.toluaL_exception(L, e));
        }
    }
    private bool LoadConfig()
    {
        try
        {
            if (m_uiCategoryConfigMap == null || !m_uiCategoryConfigMap.Any())
            {
                m_uiCategoryConfigMap = UICategoryConfig.LoadConfig();
            }

            if (m_uiItemConfigMap == null || !m_uiItemConfigMap.Any())
            {
                m_uiItemConfigMap = UIItemConfig.LoadConfig();
            }
        }
        catch (Exception e)
        {
            LogModule.ErrorLog("Exception in load UICategoryConfig, {0}\n{1}", e.Message, e.StackTrace);
            return(false);
        }
        return(true);
    }
    /// <summary>
    /// Create a UI
    /// </summary>
    /// <param name="p_type">UI category: fullscreen, window, popup, etc</param>
    /// <param name="p_name">name you defined</param>
    /// <param name="p_mediatorType"></param>
    /// <param name="p_prefab">prefab to instantiate</param>
    /// <param name="p_viewInitCallBack"></param>
    /// <param name="p_viewRefreshCallBack"></param>
    /// <param name="p_allocateDepth">allocate several panel depth to ui</param>
    /// <param name="p_viewName"></param>
    /// <param name="isShowAnimation"></param>
    private void CreateUIInternal(UIItemConfig p_config, GameObject p_prefab, DelegateHelper.TableDelegate p_viewInitCallBack, DelegateHelper.TableDelegate p_viewRefreshCallBack = null, bool isShowAnimation = true)
    {
        try
        {
            if (!m_UICategoryMap.ContainsKey(p_config.Type))
            {
                throw new KeyNotFoundException(string.Format("Key: {0} not found in UI Category.", p_config.Type));
            }

            if (p_prefab == null)
            {
                throw new Exception("Cannot create UI cause no res provided.");
            }

            if (m_UICategoryMap[p_config.Type].RemainingDepth <= 0)
            {
                LogModule.WarningLog("Cannot create UI: {0} cause remaining depth of {1} is {2}", p_config.Name, p_config.Type, m_UICategoryMap[p_config.Type].RemainingDepth);
                return;
            }

            //Create UI
            var     root  = Utils.AddChild(m_UICategoryMap[p_config.Type].RootObject.transform, p_config.Name);
            UIPanel panel = root.AddComponent <UIPanel>();

            var ui       = NGUITools.AddChild(root, p_prefab);
            var viewBase = ui.AddComponent <UIViewBase>();
            viewBase.Name = p_config.Name;

            //Initialize UI
            LuaTable view     = null;
            object   mediator = null;

            if (!string.IsNullOrEmpty(p_config.ViewName))
            {
                view           = LuaHelper.GetOutletComponent(ui, p_config.ViewName).m_LuaTable;
                view["UIName"] = p_config.Name;
            }

            if (!string.IsNullOrEmpty(p_config.MediatorType))
            {
                mediator = Activator.CreateInstance(Type.GetType(p_config.MediatorType));
                MediatorManager.GetInstance().Add((IMediator)mediator);
                ((IUIMediator)mediator).m_UIName = p_config.Name;
            }

            if (!string.IsNullOrEmpty(p_config.ViewName) && !string.IsNullOrEmpty(p_config.MediatorType))
            {
                view["Mediator"] = mediator;
                ((IUIMediator)mediator).m_View = view;
            }

            m_UIItemMap.Add(p_config.Name, new UIItem()
            {
                CategoryName = p_config.Type,
                Name         = p_config.Name,
                PanelDepth   = panel.sortingOrder,
                RootObject   = root,
                ViewBase     = viewBase,
                ViewName     = p_config.ViewName,
                View         = view,
                Mediator     = mediator,
                UIObject     = ui,
                BundlePath   = p_config.BundleName
            });

            //Get depth and set.
            int minDepth = m_UICategoryMap[p_config.Type].GetNewItemDepth();
            panel.depth = minDepth;
            int maxDepth = Utils.SetUILayer(ui, minDepth);
            if (maxDepth > 0)
            {
                m_UICategoryMap[p_config.Type].AddItem(m_UIItemMap[p_config.Name], maxDepth - minDepth + 1);
            }
            else
            {
                m_UICategoryMap[p_config.Type].AddItem(m_UIItemMap[p_config.Name], 1);
            }

            //Add delegate
            if (isShowAnimation)
            {
                if (p_viewInitCallBack != null && m_UIItemMap[p_config.Name].View != null)
                {
                    Action removeInitAction = null;
                    Action initAction       = () =>
                    {
                        p_viewInitCallBack(m_UIItemMap[p_config.Name].View);
                        removeInitAction();
                    };

                    removeInitAction = () =>
                    {
                        m_UIItemMap[p_config.Name].ViewBase.OnOpenUIComplete -= initAction;
                    };

                    m_UIItemMap[p_config.Name].ViewBase.OnOpenUIComplete += initAction;
                }

                if (p_viewRefreshCallBack != null && m_UIItemMap[p_config.Name].View != null)
                {
                    m_UIItemMap[p_config.Name].ViewBase.OnOpenUIComplete += () =>
                    {
                        p_viewRefreshCallBack(m_UIItemMap[p_config.Name].View);
                    };
                }

                m_UIItemMap[p_config.Name].ViewBase.OnCloseUIComplete += () =>
                {
                    CloseUIInternal(p_config.Name);
                };
            }
            //Init
            else
            {
                if (p_viewInitCallBack != null && m_UIItemMap[p_config.Name].View != null)
                {
                    p_viewInitCallBack(m_UIItemMap[p_config.Name].View);
                }
            }

            ExeAfterOpenUI(p_config, p_viewRefreshCallBack, isShowAnimation);

            return;
        }
        catch (Exception e)
        {
            LogModule.ErrorLog("Exception in create UI intrenal, {0}\n{1}", e.Message, e.StackTrace);
            return;
        }
    }