using System;
using System.Collections.Concurrent;
using System.Threading;

namespace Server.Core
{
    public static partial class ReferencePool
    {
        private class Pool
        {
            private readonly Type objectType;

            private readonly int MaxCapacity;

            public int NumItems;

            private readonly ConcurrentQueue<IReference> _items = new ConcurrentQueue<IReference>();

            private IReference FastItem;
            
            public Pool(Type objectType, int maxCapacity)
            {
                this.objectType = objectType;
                MaxCapacity = maxCapacity;
            }

            public object Get()
            {
                IReference item = FastItem;
                if (item == null || Interlocked.CompareExchange(ref FastItem,null,item) != item)
                {
                    if (_items.TryDequeue(out item))
                    {
                        Interlocked.Decrement(ref NumItems);
                        return item;
                    }

                    return Activator.CreateInstance(this.objectType);
                }

                return item;
            }

            public void Return(IReference obj)
            {
                if (FastItem != null || Interlocked.CompareExchange(ref FastItem,obj,null) != null)
                {
                    if (Interlocked.Increment(ref NumItems) <= MaxCapacity)
                    {
                        _items.Enqueue(obj);
                        return;
                    }
                    
                    Interlocked.Decrement(ref NumItems);
                }
            }
        }
    }
}