using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MrWu.Debug;

namespace Server.Core
{
    public class CoroutineLockQueue : Reference
    {
        /// <summary>
        /// CoroutineLockType
        /// </summary>
        public int Type { get; private set; }

        public long Key { get; private set; }

        public CoroutineLockManager CoroutineLockManager { get; private set; }

        private ObjectRef<CoroutineLock> currentCoroutineLock;

        public CoroutineLock CurrentCoroutineLock
        {
            get { return this.currentCoroutineLock; }
            set { this.currentCoroutineLock = value; }
        }

        private readonly Queue<WaitCoroutineLock> queue = new Queue<WaitCoroutineLock>();

        public int Count
        {
            get { return this.queue.Count; }
        }

        public static CoroutineLockQueue Create(int type, long key, CoroutineLockManager coroutineLockManager)
        {
            CoroutineLockQueue coroutineLockQueue = ReferencePool.Fetch<CoroutineLockQueue>();
            coroutineLockQueue.Type = type;
            coroutineLockQueue.Key = key;
            coroutineLockQueue.CoroutineLockManager = coroutineLockManager;
            return coroutineLockQueue;
        }

        public override void Dispose()
        {
            this.queue.Clear();
            this.Type = CoroutineLockType.None;
            this.CurrentCoroutineLock = null;
            this.CoroutineLockManager = null;
            ReferencePool.Recycle(this);
        }

        private CoroutineLock New(int level)
        {
            CoroutineLock coroutineLock =
                CoroutineLock.Create(this.Type, Key, level, CoroutineLockManager);
            return coroutineLock;
        }

        public async Task<CoroutineLock> Wait(int time)
        {
            if (this.CurrentCoroutineLock == null)
            {
                CoroutineLock coroutineLock = New(1);
                this.CurrentCoroutineLock = coroutineLock;
                Debug.Log("第一个锁，直接返回!");
                return coroutineLock;
            }

            WaitCoroutineLock waitCoroutineLock = WaitCoroutineLock.Create();
            this.queue.Enqueue(waitCoroutineLock);
            if (time > 0)
            {
                // 超时处理
            }

            Debug.Log($"添加到等待队列:{Count}");
            this.CurrentCoroutineLock = await waitCoroutineLock.Wait();
            return this.CurrentCoroutineLock;
        }

        public bool Notify(int level)
        {
            while (this.queue.Count > 0)
            {
                WaitCoroutineLock waitCoroutineLock = this.queue.Dequeue();

                if (waitCoroutineLock.IsDisposed())
                {
                    continue;
                }

                CoroutineLock coroutineLock = New(level);
                waitCoroutineLock.SetResult(coroutineLock);
                return true;
            }

            return false;
        }
    }
}