using System.Collections.Generic;
using System.Linq;
using UnityEngine;

//TODO: 加一个公共的托管父类
public class ObjectPool : System.IDisposable
{
    private static ObjectPool instance;
    public static ObjectPool Instance
    {
        get
        {
            instance ??= new ObjectPool();
            return instance;
        }
        set { instance = value; }
    }

    public Dictionary<string, Queue<GameObject>> objectPool = new();
    public Dictionary<string, Transform> objectPoolRoot = new();
    //private GameObject thePool;
    private GameObject pool;
    

    
    public GameObject GetObject(GameObject prefab)
    {
        GameObject _object;
        if (!objectPool.ContainsKey(prefab.name) || objectPool[prefab.name].Count == 0)
        {
            _object = GameObject.Instantiate(prefab);
            
            #region 防止在使用需要的时候二次Enable的补丁
            string _name = prefab.name.Replace("(Clone)", string.Empty);
            _object.name = _name;
            #endregion


            //默认设置层级
            if (!objectPool.ContainsKey(_name)) objectPool.Add(_name, new Queue<GameObject>());
            if (pool == null) pool = new GameObject("ObjectPool");//保证有父物体 对象池

            Transform theChildPoolRoot;
            if (!objectPoolRoot.TryGetValue(_object.name, out Transform childPoolRoot))
            {
                string objectPoolName = _object.name + "Pool";
                GameObject childPool = new(objectPoolName);
                childPool.transform.SetParent(pool.transform);  //设置父物体

                theChildPoolRoot = childPool.transform;
                objectPoolRoot.Add(_object.name, theChildPoolRoot);
            }
            else theChildPoolRoot = childPoolRoot;

            _object.transform.SetParent(theChildPoolRoot);      //预制体归档
        }
        //取出所需对象返回
        else
        {
            _object = objectPool[prefab.name].Dequeue();
        }

        _object.SetActive(true);
        return _object;
    }
    public GameObject GetObject(GameObject prefab,Vector3 pos)
    {
        GameObject _object;
        if (!objectPool.ContainsKey(prefab.name) || objectPool[prefab.name].Count == 0)
        {
            _object = GameObject.Instantiate(prefab,pos,Quaternion.identity);

            #region 防止在使用需要的时候二次Enable的补丁
            string _name = prefab.name.Replace("(Clone)", string.Empty);
            _object.name = _name;
            #endregion
        }
        //取出所需对象返回
        else
        {
            _object = objectPool[prefab.name].Dequeue();
        }

        _object.transform.position = pos;
        _object.SetActive(true);
        return _object;
    }


    public void PushObject(GameObject prefab)
    {
        //string _name = prefab.name.Replace("(Clone)", string.Empty);
        //prefab.name = _name;
        string _name = prefab.name;

        if (!objectPool.ContainsKey(_name)) objectPool.Add(_name, new Queue<GameObject>());
        if (objectPool[_name].Contains(prefab))
        {
            prefab.SetActive(false);
            return;
        }

        objectPool[_name].Enqueue(prefab);

        prefab.SetActive(false);

        if (pool == null)        //保证有父物体 对象池
        {
            pool = new GameObject("ObjectPool");
        }

        Transform theChildPoolRoot;
        if (!objectPoolRoot.TryGetValue(prefab.name, out Transform childPoolRoot))
        {
            string objectPoolName = prefab.name + "Pool";
            GameObject childPool = new(objectPoolName);
            childPool.transform.SetParent(pool.transform);  //设置父物体

            theChildPoolRoot = childPool.transform;
            objectPoolRoot.Add(prefab.name, theChildPoolRoot);
        }
        else theChildPoolRoot = childPoolRoot;

        prefab.transform.SetParent(theChildPoolRoot);      //预制体归档
    }


    public void ResetObjectPool()
    {
        if (objectPool.Count > 0)
            objectPool.Clear();
    }

    //?在这里统计有没有激活的真有用吗
    public int HasActiveObject(GameObject prefab)
    {
        if (!objectPool.ContainsKey(prefab.name) || objectPool[prefab.name].Count == 0) return 0;
        else
        {
            int count = 0;
            for(int i = 0;i< objectPool[prefab.name].Count; i++)
            {
                if (objectPool[prefab.name].ElementAt(i).activeSelf) count++;
            }
            return count;
        }
    }

    public void Dispose()
    {
        ResetObjectPool();
    }
}