using System.Collections.Generic;
using UnityEngine;
using FairyGUI;

namespace RedHotRoast
{
    public class GLoaderPool
    {
        private static GLoaderPool _instance;
        public static GLoaderPool Instance => _instance ??= new GLoaderPool();

        private readonly Queue<GLoader> pool = new Queue<GLoader>();
        private readonly LinkedList<GLoader> inUseLoaders = new LinkedList<GLoader>(); // 维护活跃顺序（LRU）

        private int maxCount = 10;   // 最大池子数量
        private int _width = 0;
        private int _height = 0;

        private bool _autoDisposeTexture = true; // 是否自动释放贴图

        private GLoaderPool() { }

        /// <summary>
        /// 初始化 Loader 池
        /// </summary>
        public void Init(GComponent parentObj, int maxPoolCount, int width, int height, bool autoDisposeTexture = true)
        {
            maxCount = maxPoolCount;
            _width = width;
            _height = height;
            _autoDisposeTexture = autoDisposeTexture;

            DisposeAll();

            // 预创建 loader
            for (int i = 0; i < maxCount; i++)
            {
                var loader = CreateLoader();
                pool.Enqueue(loader);
            }
        }

        private GLoader CreateLoader()
        {
            var loader = new GLoader
            {
                fill = FillType.ScaleMatchWidth,
                align = AlignType.Center,
                verticalAlign = VertAlignType.Top,
                visible = false
            };
            loader.SetSize(_width, _height);
            return loader;
        }

        /// <summary>
        /// 从池中获取 Loader
        /// </summary>
        public GLoader GetLoader()
        {
            GLoader loader = null;

            // 如果池子里有，直接取
            if (pool.Count > 0)
            {
                loader = pool.Dequeue();
            }
            else if (inUseLoaders.Count >= maxCount)
            {
                // 如果池满了，回收最久未使用的一个（LRU）
                loader = inUseLoaders.First.Value;
                inUseLoaders.RemoveFirst();
                RecycleLoader(loader);
                Debug.Log($"[LRU回收] 回收并复用一个 Loader");
            }
            else
            {
                // 未达到上限，新建
                loader = CreateLoader();
            }

            // 标记为使用中，放到链表末尾（最近使用）
            inUseLoaders.AddLast(loader);
            loader.visible = true;
            return loader;
        }

        /// <summary>
        /// 归还 Loader
        /// </summary>
        public void ReturnLoader(GLoader loader)
        {
            if (loader == null) return;

            if (inUseLoaders.Contains(loader))
            {
                inUseLoaders.Remove(loader);
                RecycleLoader(loader);
                pool.Enqueue(loader);
            }
            else
            {
                Debug.LogWarning("尝试归还未分配的 GLoader");
            }
        }

        /// <summary>
        /// 回收 loader 的资源
        /// </summary>
        private void RecycleLoader(GLoader loader)
        {
            if (_autoDisposeTexture && loader.texture != null)
            {
                loader.texture.Dispose();
            }
            loader.url = null;
            loader.texture = null;
            loader.visible = false;
        }

        /// <summary>
        /// 更新 Loader 的使用顺序（需要主动调用，避免 LRU 误判）
        /// </summary>
        public void TouchLoader(GLoader loader)
        {
            if (loader == null || !inUseLoaders.Contains(loader)) return;
            inUseLoaders.Remove(loader);
            inUseLoaders.AddLast(loader); // 移到链表末尾，标记为最新使用
        }
        
        public bool IsFromPool(GLoader loader)
        {
            return inUseLoaders.Contains(loader) || pool.Contains(loader);
        }

        public int GetPoolCount() => pool.Count;
        public int GetInUseCount() => inUseLoaders.Count;

        /// <summary>
        /// 清理全部
        /// </summary>
        public void DisposeAll()
        {
            foreach (var loader in pool)
            {
                loader?.Dispose();
            }
            foreach (var loader in inUseLoaders)
            {
                loader?.Dispose();
            }
            pool.Clear();
            inUseLoaders.Clear();
        }
    }
}
