using System;
using System.Collections.Generic;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;
using Object = UnityEngine.Object;
using ReferenceCollector = Fort23.Mono.ReferenceCollector;

namespace Mono
{
    public class UIManager : Utility.Singleton<UIManager>
    {
        public Dictionary<string, UIPanel> AllPanel = new Dictionary<string, UIPanel>();


        public Dictionary<string, List<UICom>> AllUIComPool = new Dictionary<string, List<UICom>>();

        public enum UILayer
        {
            Bottom, //最底层UI（主界面）
            Middle, //中间UI（各种Panel）
            Top, //最顶层UI节点
        }

        public GameObject UIRoot;

        public RectTransform BottomRoot;
        public RectTransform MiddleRoot;
        public RectTransform TopRoot;

        public ReferenceCollector ReferenceCollector;

        public void SetUIRoot(GameObject gameObject)
        {
            UIRoot = gameObject;
            ReferenceCollector = gameObject.GetComponent<ReferenceCollector>();
            BottomRoot = ReferenceCollector.Get<RectTransform>("BottomRoot");
            MiddleRoot = ReferenceCollector.Get<RectTransform>("MiddleRoot");
            TopRoot = ReferenceCollector.Get<RectTransform>("TopRoot");
        }


        /// <summary>
        /// 加载打开一个界面
        /// </summary>
        /// <param name="uiLayer"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T LoadAndOpenPanel<T>(UILayer uiLayer) where T : UIPanel, new()
        {
            Type type;
            type = typeof(T);
            T uiPanel;

            // 获取UI绑定属性
            UIBindingAttribute uiBindingAttribute = type.GetCustomAttribute(typeof(UIBindingAttribute)) as UIBindingAttribute;
            if (uiBindingAttribute == null)
            {
                return null;
            }

            Transform root = null;

            switch (uiLayer)
            {
                case UILayer.Bottom:
                    root = BottomRoot;
                    break;
                case UILayer.Middle:
                    root = MiddleRoot;
                    break;
                case UILayer.Top:
                    root = TopRoot;
                    break;
            }

            string name = type.ToString();

            if (!AllPanel.ContainsKey(name))
            {
                uiPanel = new T();

                GameObject prefab = Resources.Load<GameObject>("UIPanel/" + uiBindingAttribute.prefab);
                GameObject gameObject = Object.Instantiate(prefab, root);
                uiPanel.SetUIRoot(gameObject);
                AllPanel.Add(name, uiPanel);
            }
            else
            {
                uiPanel = (T)AllPanel[name];
                uiPanel.Root.transform.SetParent(root);
            }


            uiPanel.DelEvent();
            uiPanel.Show();


            return uiPanel;
        }

        /// <summary>
        /// 关闭界面
        /// </summary>
        /// <param name="isClose"></param>
        /// <typeparam name="T"></typeparam>
        public void HideUIPanel<T>(bool isClose = false) where T : UIPanel, new()
        {
            Type type;
            type = typeof(T);
            string name = type.ToString();

            if (AllPanel.ContainsKey(name))
            {
                if (isClose)
                {
                    AllPanel[name].Dispose();
                    AllPanel.Remove(name);
                }
                else
                {
                    AllPanel[name].Hide();
                }
            }
            else
            {
                Debug.Log("没有这个界面");
            }
        }


        /// <summary>
        /// 创建组件
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="root"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T CreatUICom<T>(UIBasic parent, Transform root) where T : UICom, new()
        {
            Type type;
            type = typeof(T);
            T uiCom;

            // 获取UI绑定属性
            UIBindingAttribute uiBindingAttribute = type.GetCustomAttribute(typeof(UIBindingAttribute)) as UIBindingAttribute;
            if (uiBindingAttribute == null)
            {
                return null;
            }

            string name = type.ToString();

            if (!AllUIComPool.ContainsKey(name))
            {
                uiCom = new T();
                GameObject prefab = Resources.Load<GameObject>("UICom/" + uiBindingAttribute.prefab);
                GameObject gameObject = Object.Instantiate(prefab, root);
                uiCom.SetUIRoot(gameObject);
            }
            else
            {
                uiCom = (T)AllUIComPool[name][0];
                AllUIComPool[name].Remove(uiCom);
                if ( AllUIComPool[name].Count==0)
                {
                    AllUIComPool.Remove(name);
                }
            }
            uiCom.Root.transform.SetParent(root);

            if (!parent.AllUICom.ContainsKey(name))
            {
                List<UICom> uiComs = new List<UICom>();
                uiComs.Add(uiCom);
                parent.AllUICom.Add(name, uiComs);
            }
            else
            {
                parent.AllUICom[name].Add(uiCom);
            }
            
            

            uiCom.DelEvent();
            uiCom.Show();
            return uiCom;
        }

        /// <summary>
        /// 回收组件
        /// </summary>
        /// <param name="uiCom"></param>
        public void RecUICom(UIBasic parent, UICom uiCom)
        {
            string name = uiCom.ToString();
            if (!AllUIComPool.ContainsKey(name))
            {
                List<UICom> coms = new List<UICom>();
                coms.Add(uiCom);
                uiCom.Hide();
                AllUIComPool.Add(name, coms);
            }
            else
            {
                uiCom.Hide();
                AllUIComPool[name].Add(uiCom);
            }

            if (parent.AllUICom.ContainsKey(name))
            {
                parent.AllUICom[name].Remove(uiCom);
                if (parent.AllUICom[name].Count == 0)
                {
                    parent.AllUICom.Remove(name);
                }
            }
        }
    }
}