using System.Collections.Generic;
using UnityEngine;

namespace WS
{
    [ObjectSystem]
    public class GamePoolManagerAwake : AwakeSystem<GamePoolManager>
    {
        public override void Awake(GamePoolManager self)
        {
            self.Awake();
        }
    }

    ///<summary>GameObject 对象池</summary>
    public class GamePoolManager : SingleComponent<GamePoolManager>
    {
        ///<summary>Game对象容器</summary>
        private Dictionary<string, List<GameObject>> DicObject = new Dictionary<string, List<GameObject>>();
        ///<summary>所有的配置</summary>
        private Dictionary<string, PoolClear> TimerInfos = new Dictionary<string, PoolClear>();
        ///<summary>计时器</summary>
        private Dictionary<string, TimerEntity> Timers = new Dictionary<string, TimerEntity>();
        ///<summary>回收后对象的父节点</summary>
        private Transform PoolRootParent;

        public void Awake()
        {
            PoolRootParent = new GameObject("PoolRootParent").transform;
            PoolRootParent.SetParent(Game.Init);

            List<PoolClear> poolClears = ConfigHelper.LoadConfig<List<PoolClear>>("Config/Framework/PoolClear");
            for (int i = 0; i < poolClears.Count; i++)
            {
                TimerInfos.Add(poolClears[i].Name, poolClears[i]);
            }
        }

        ///<summary>定时移除对象</summary>
        private void TimeDestroyObj(PoolClear clear)
        {
            List<GameObject> listobj = GetKeyAllObj(clear.Name);
            if (listobj.Count > clear.CullSave)
            {
                List<GameObject> listset = listobj.FindAll(o => o.activeSelf == false);
                int count = listobj.Count - clear.CullSave;
                if (listset.Count > count)
                {
                    if (count > clear.CullNextCount) count = clear.CullNextCount;

                    for (int i = count - 1; i >= 0; i--)
                    {
                        UnityEngine.Object.Destroy(listset[i]);
                        listobj.RemoveAt(i);
                    }
                }
            }
        }

        /// <summary>增加</summary>
        private void Add(string key, GameObject go)
        {
            if (!DicObject.ContainsKey(key))
            {
                DicObject.Add(key, new List<GameObject>());
                if (TimerInfos.ContainsKey(key))
                {
                    PoolClear clear = TimerInfos[key];
                    TimerEntity time = TimerComponent.Instance.Wait(clear.CullTime, () => { TimeDestroyObj(clear); }, true);
                    Timers.Add(clear.Name, time);
                }
            }
            DicObject[key].Add(go);
        }

        /// <summary>将对象归入池中</summary>
        public void Recovery(GameObject destoryGo)
        {
            if (destoryGo != null)
            {
                destoryGo.SetActive(false);
                destoryGo.transform.SetParent(PoolRootParent);
            }
        }

        /// <summary>将对象归入池中</summary>
        public void Recovery(GameObject tempGo, float delay)
        {
            DelayRecovery(tempGo, delay);
        }

        /// <summary>延迟销毁</summary>
        private async void DelayRecovery(GameObject destoryGO, float delay)
        {
            await TimerComponent.Instance.WaitAsync(delay);
            Recovery(destoryGO);
        }

        /// <summary>取出可用的物体</summary>
        private GameObject FindUsable(string key)
        {
            if (DicObject.ContainsKey(key))
            {
                for (int i = DicObject[key].Count - 1; i >= 0; i--)
                {
                    if (DicObject[key][i] == null)
                    {
                        DicObject[key].RemoveAt(i);
                    }
                    else if (!DicObject[key][i].activeSelf)
                    {
                        return DicObject[key][i];
                    }
                }
            }
            return null;
        }

        #region -- obj --

        /// <summary>创建实例</summary>
        /// <param name="obj">物体</param>
        public GameObject CreateObject(GameObject obj)
        {
            return CreateObject(obj, Vector3.zero, Quaternion.identity);
        }

        /// <summary>创建实例</summary>
        /// <param name="obj">物体</param>
        public GameObject CreateObject(GameObject obj, Vector3 position)
        {
            return CreateObject(obj, position, Quaternion.identity);
        }

        /// <summary>创建实例</summary>
        /// <param name="obj">物体</param>
        public GameObject CreateObject(GameObject obj, Vector3 position, Quaternion quaternion)
        {
            GameObject tempGo = FindUsable(obj.name);
            if (tempGo != null)
            {
                tempGo.transform.SetParent(null, false);
                tempGo.transform.position = position;
                tempGo.transform.rotation = quaternion;
                tempGo.SetActive(true);
            }
            else
            {
                tempGo = UnityEngine.Object.Instantiate(obj, position, quaternion);
                Add(obj.name, tempGo);
            }
            return tempGo;
        }

        ///<summary>创建实例 - 并回收</summary>
        /// <param name="obj">物体</param>
        public void CreateObject(GameObject obj, Vector3 position, float delay)
        {
            GameObject go = CreateObject(obj, position, Quaternion.identity);
            Recovery(go, delay);
        }

        ///<summary>创建实例 - 并回收</summary>
        /// <param name="obj">物体</param>
        public void CreateObject(GameObject obj, Vector3 position, Quaternion quaternion, float delay)
        {
            GameObject go = CreateObject(obj, position, quaternion);
            Recovery(go, delay);
        }

        #endregion

        #region -- path --

        /// <summary>创建实例</summary>
        /// <param name="key">key = path</param>
        public GameObject CreateObject(string key)
        {
            return CreateObject(key, Vector3.zero, Quaternion.identity);
        }

        /// <summary>创建实例</summary>
        /// <param name="key">key = path</param>
        public GameObject CreateObject(string key, Vector3 position)
        {
            return CreateObject(key, position, Quaternion.identity);
        }

        ///<summary>创建实例 - 并回收</summary>
        /// <param name="key">key = path</param>
        public void CreateObject(string key, Vector3 position, float delay)
        {
            GameObject go = CreateObject(key, position, Quaternion.identity);
            Recovery(go, delay);
        }

        ///<summary>创建实例 - 并回收</summary>
        /// <param name="key">key = path</param>
        public void CreateObject(string key, Vector3 position, Quaternion quaternion, float delay)
        {
            GameObject go = CreateObject(key, position, quaternion);
            Recovery(go, delay);
        }

        /// <summary>创建实例</summary>
        /// <param name="key">key = path</param>
        public GameObject CreateObject(string key, Vector3 position, Quaternion quaternion)
        {
            GameObject tempGo = FindUsable(key);
            if (tempGo != null)
            {
                tempGo.transform.SetParent(null,false);
                tempGo.transform.position = position;
                tempGo.transform.rotation = quaternion;
                tempGo.SetActive(true);
            }
            else
            {
                GameObject go = Resources.Load<GameObject>(key);
                tempGo = UnityEngine.Object.Instantiate(go, position, quaternion);
                Add(key, tempGo);
            }
            return tempGo;
        }

        #endregion

        ///<summary>获取key的所有对象</summary>
        public List<GameObject> GetKeyAllObj(string key)
        {
            if (DicObject.ContainsKey(key))
            {
                return DicObject[key];
            }
            return null;
        }

        /// <summary>清空某类游戏对象</summary>
        public void Clear(string key, bool isRemove = true)
        {
            if (DicObject.ContainsKey(key))
            {
                List<GameObject> list = DicObject[key];
                for (int i = 0; i < list.Count; i++)
                {
                    UnityEngine.Object.Destroy(list[i]);
                }
            }
            if (isRemove)
                DicObject.Remove(key);
            if (Timers.ContainsKey(key))
            {
                Timers[key].Dispose();
                Timers.Remove(key);
            }
        }

        /// <summary>清空池中所有游戏对象</summary>
        public void ClearAll()
        {
            foreach (var item in DicObject)
            {
                Clear(item.Key, false);
            }
            DicObject.Clear();
        }

        public override void Dispose()
        {
            base.Dispose();
            ClearAll();
            TimerInfos.Clear();
            Timers.Clear();
        }
    }
}