using System.Collections.Concurrent;
using System.Collections.Generic;
using MrWu.Debug;
using Server.Core;
using Server.Net;

namespace Server
{
    /// <summary>
    /// 这个是主线程处理的
    /// </summary>
    public class UserSessionManager : Singleton<UserSessionManager>
    {
        /// <summary>
        /// 用户会话事件队列
        /// </summary>
        private readonly ConcurrentQueue<UserSessionEvt> evtQueue = new ConcurrentQueue<UserSessionEvt>();

        /// <summary>
        /// 用户的Session
        /// </summary>
        private Dictionary<long, UserSession> UserSessions = new Dictionary<long, UserSession>();

        public bool IsGame { get; private set; }

        public UserSessionManager(bool isGame)
        {
            IsGame = isGame;
        }

        public void AddUserSessionEvt(UserSessionEvt evt)
        {
            evtQueue.Enqueue(evt);
        }

        public void Update()
        {
            int count = evtQueue.Count;
            while (count -- > 0)
            {
                if (!evtQueue.TryDequeue(out var evt))
                {
                    break;
                }
                
                switch (evt.EvtType)
                {
                    case UserSessionEvtType.Connected:
                    {
                        UserSession userSession = new UserSession(evt.Id, evt.InstanceId);
                        if (UserSessions.ContainsKey(evt.Id))
                        {
                            Debug.Error($"怎么会存在这个链接实例:{evt.Id}");
                        }
                        
                        userSession.IsDisConnected = false;
                        userSession.RemoteIPAddress = evt.RemoteIPAddress;
                        UserSessions[evt.Id] = userSession;
                    }
                        break;
                    case UserSessionEvtType.Fin:
                    {
                        //断开处理
                        if (UserSessions.TryGetValue(evt.Id, out UserSession userSession))
                        {
                            if (evt.InstanceId != userSession.InstanceId)
                            {
                                break;
                            }

                            UserFin(userSession);
                        }
                    }
                        break;
                    case UserSessionEvtType.ReceivePack:
                    {
                        if (UserSessions.TryGetValue(evt.Id,out UserSession userSession))
                        {
                            if (evt.InstanceId != userSession.InstanceId)
                            {
                                Debug.Error("实例ID改变，不处理消息!");
                            }
                            else
                            {
                                //要不这里就单独处理包,不走MessageDispatcher
                                userSession.RemoteIPAddress = evt.RemoteIPAddress;
                                evt.GamePacket.Session = ProxySession.Create(userSession);
                                MessageDispatcher.Instance.AddPack(evt.GamePacket);
                            }
                        }
                        else
                        {
                            Debug.Error("未找到收包的链接!");
                        }
                    }
                        break;
                }
                
                evt.Dispose();
            }
        }

        /// <summary>
        /// 用户断开链接
        /// </summary>
        public void UserFin(UserSession userSession)
        {
            if (UserSessions.TryGetValue(userSession.Id, out UserSession _session))
            {
                if (_session == userSession)
                {
                    UserSessions.Remove(userSession.Id);

                    userSession.IsDisConnected = true;
                    int userid = 0;
                    if (userSession.UserData != null)
                    {
                        userid = userSession.UserData.Userid;
                    }
                    if (userSession.UserData != null && IsGame)
                    {
                        if (!GameSessionManager.Instance.RemovePlayerSession(userid, userSession))
                        {
                            Debug.Error($"玩家未正常移除! {userid}");
                        }
                        Debug.ImportantLog($"玩家离线，注销Session {userid}");
                    }
                    userSession.ClearUserData();
                    if (userid > 0)
                    {
                        GameDispatcher.Instance.Dispatch(GameMsgId.DisConnected, userid);
                    }
                }
                else
                {
                    Debug.Info("移除失败，不是同一个Session!");
                }
            }
            else
            {
                Debug.Info("移除失败，没找到Session!");
            }
        }
    }

    public class UserSessionEvt : Reference
    {
        /// <summary>
        /// 链接ID
        /// </summary>
        public long Id { get; private set; }

        /// <summary>
        /// 实例ID
        /// </summary>
        public long InstanceId { get; private set; }

        /// <summary>
        /// IP地址 链接的时候会赋值
        /// </summary>
        /// <returns></returns>
        public string RemoteIPAddress { get; private set; }

        public GamePacket GamePacket { get; private set; }

        public UserSessionEvtType EvtType { get; private set; }

        public static UserSessionEvt Create(long id, long instanceId, string remoteIpAddress)
        {
            UserSessionEvt self =ReferencePool.Fetch<UserSessionEvt>();
            self.Id = id;
            self.InstanceId = instanceId;
            self.RemoteIPAddress = remoteIpAddress;
            self.EvtType = UserSessionEvtType.Connected;
            return self;
        }

        public static UserSessionEvt Create(long id, long instanceId, GamePacket gamePacket,string remoteIpAddress)
        {
            UserSessionEvt self = ReferencePool.Fetch<UserSessionEvt>();
            self.Id = id;
            self.InstanceId = instanceId;
            self.GamePacket = gamePacket;
            self.RemoteIPAddress = remoteIpAddress;
            self.EvtType = UserSessionEvtType.ReceivePack;
            return self;
        }

        public static UserSessionEvt Create(long id,long instanceId,UserSessionEvtType evtType)
        {
            var evt = new UserSessionEvt();
            evt.Id = id;
            evt.InstanceId = instanceId;
            evt.EvtType = evtType;
            return evt;
        }

        public override void Dispose()
        {
            RemoteIPAddress = null;
            GamePacket = null;
            ReferencePool.Recycle(this);
        }
    }

    public enum UserSessionEvtType
    {
        /// <summary>
        /// 链接
        /// </summary>
        Connected,
        
        /// <summary>
        /// 断开链接
        /// </summary>
        Fin,
        
        /// <summary>
        /// 收包
        /// </summary>
        ReceivePack,
    }
}