using System.Collections.Concurrent;
using System.Threading.Tasks;
using GameMessage;
using MrWu.Debug;
using Server.Core;
using Server.Core.Extend;

namespace Server.Net
{
    /// <summary>
    /// 游戏包
    /// </summary>
    public class GamePacket : Reference
    {
        /// <summary>
        /// 消息Code
        /// </summary>
        public int OpCode { get; private set; }

        /// <summary>
        /// 消息数据
        /// </summary>
        public MessageData MessageData { get; private set; }

        /// <summary>
        /// 谁发来的 - 包处理完会释放
        /// </summary>
        public IUserSession Session { get; set; }

        /// <summary>
        /// 任务
        /// </summary>
        private ConcurrentQueue<Task> Tasks = new ConcurrentQueue<Task>();
        
        public static GamePacket Create(int opCode, MessageData messageData)
        {
            GamePacket packet = ReferencePool.Fetch<GamePacket>();
            packet.OpCode = opCode;
            packet.MessageData = messageData;
            
#if DEBUG
            if (!packet.Tasks.IsEmpty)
            {
                Debug.Fatal("Packet has task!");
            }
#endif
            
            return packet;
        }
        
        public static GamePacket Create(int opCode, MessageData messageData,IUserSession session)
        {
            GamePacket packet = ReferencePool.Fetch<GamePacket>();
            packet.OpCode = opCode;
            packet.MessageData = messageData;
            packet.Session = session;

            #if DEBUG
            if (!packet.Tasks.IsEmpty)
            {
                Debug.Fatal("Packet has task!");
            }
            #endif
            
            return packet;
        }

        public void BeginTask(Task task)
        {
            if (task == null)
            {
                return;
            }
            Tasks.Enqueue(task);
        }

        public Task Wait()
        {
            if (Tasks.IsEmpty)
            {
                return Task.CompletedTask;
            }
            //等待所有任务完成
            return Task.WhenAll(Tasks);
        }

        public override void Dispose()
        {
            if (IsFromPool)
            {
                MessageData = null;
                if (Session is ProxySession proxySession)
                {
                    proxySession.Dispose();
                }

                Tasks.Clear();
                Session = null;
                ReferencePool.Recycle(this);
            }
        }
    }
}