using System.Collections.Generic;
using MrWu.Basic;
using MrWu.Debug;
using Server;
using Server.Data;

namespace Game.Queue
{
    public abstract class GoldQueueBase : IQueueControll
    {
        public abstract TingManager ting { get; protected set; }
        
        public abstract int MinCnt { get; }
        
        public abstract int MaxCnt { get; }

        /// <summary>
        /// 排队的列表..用户,,,注意 如果玩家离线, 或者发送退出桌子的命令，从列表中删除用户,按排队时间排序
        /// </summary>
        public readonly List<PlayerDataAsyc> QueuePlayer = new List<PlayerDataAsyc>();
        
        /// <summary>
        /// 最短排上队的时间
        /// </summary>
        protected const int minqueueTime = 3;

        /// <summary>
        /// 最长排上队的时间
        /// </summary>
        protected const int maxqueueTime = 10;
        
        public virtual bool AddPlayer(PlayerDataAsyc pl, int roomid, int deskId = -1)
        {
            Desk desk = ting.GetDesk(DeskState.Idle);
            desk.Init();

            if (desk.AddPlayer(pl, roomid))
            {
                pl.queuetime = -1;
                AddQueueList(pl);

                if ((desk.state & DeskState.Idle) > 0)
                    ting.RemoveIdle(desk);
                ting.AddQueueing(desk); //闲置的桌子转变为排队的桌子
                return true;
            }

            return false;
        }

        public abstract void DoQueue();

        public virtual bool Cancel(PlayerDataAsyc pl)
        {
            return RemoveQueueList(pl);
        }

        /// <summary>
        /// 添加到排队列表
        /// </summary>
        protected virtual void AddQueueList(PlayerDataAsyc pl)
        {
            //为每个排队的人赋值上，数值...

            //先赋值上可以一起玩的人
            //ip 相同不能一起玩
            //间隔的金币数额过大不能一起玩
            //经纬度太近
            //用户与用户之间玩的次数过多
            //wifi id 一致的, wifi ssd 一样的

            int len = QueuePlayer.Count;
            for (int i = 0; i < len; i++)
            {
                var tmp = QueuePlayer[i];

                
                if (CheckPlayer(pl, tmp))
                {
                    //双方绑定为可以一起玩游戏的人
                    pl.QueueSet.Add(tmp);
                    tmp.QueueSet.Add(pl);
                }
            }

            QueuePlayer.Add(pl);
        }
        
        /// <summary>
        /// 检查两个玩家是否可以排在一起
        /// </summary>
        /// <param name="pl">玩家</param>
        /// <param name="other">其他玩家</param>
        /// <returns>true 表示可以排队在一起,false 表示可以被排在一起</returns>
        protected bool CheckPlayer(PlayerDataAsyc pl, PlayerDataAsyc other)
        {
            if (pl.isRobot || other.isRobot) //鬼不需要
                return true;

            if (GameManager.instance.noCheckAddDesk)
            {
                //不检查排队
                //Debug.Info("不检查排队!!!");
                return true;
            }
            
            if (pl.device.wmsty == 1)
                return false;

            //金币场
            //Debug.Info("金币场检查进入房间");

            if (pl.ip == other.ip)
            {
                //ip相同，不能排在一起
                Debug.Warning("ip 相同不能排在一起!");
                return false;
            }

            if (string.IsNullOrEmpty(pl.pi) && string.IsNullOrEmpty(other.pi) && pl.pi == other.pi)
            {
                Debug.Warning("同一个实名信息，不能排队在一起!");
                return false;
            }
            
            if ((pl.MatchObj != null && other.MatchObj == null) || (pl.MatchObj == null && other.MatchObj != null))
            {
                Debug.Info($"比赛的和不比赛的可以在一起玩 {pl.MatchObj == null} {other.MatchObj == null}");
                return true;
            }

            var room1 = GameManager.instance.FindRoom(pl.roomid);
            var room2 = GameManager.instance.FindRoom(other.roomid);
            if (room1 == null || room2 == null)
            {
                Debug.Error("游戏逻辑错误,来排队的两个玩家的房间找不到:" + pl.roomid + "," + other.roomid);
                return false;
            }

            if (room1.config.Queuetag != room2.config.Queuetag)
                return false;


            if (!string.IsNullOrEmpty(pl.device.wifimac) && pl.device.wifimac == other.device.wifimac)
                return false;

            return true;
        }
        
        /// <summary>
        /// 把玩家移出排队列表
        /// </summary>
        /// <param name="pl">玩家</param>
        /// <returns>存在返回true 不存在返回false</returns>
        protected virtual bool RemoveQueueList(PlayerDataAsyc pl)
        {
            if (pl == null)
                return false;
            if (pl.isRobot)
                return false;

            int len = QueuePlayer.Count;
            for (int i = 0; i < len; i++)
            {
                if (QueuePlayer[i].id == pl.id)
                {
                    foreach (var item in QueuePlayer[i].QueueSet)
                    {
                        if (!item.QueueSet.Remove(QueuePlayer[i]))
                        {
                            Debug.Error("逻辑错误，双向列表缺少值!");
                        }
                    }

                    QueuePlayer[i].QueueSet.Clear();
                    QueuePlayer.RemoveAt(i);
                    //Debug.Info($"移除排队列表!!! {QueuePlayer.Count}");
                    return true;
                }
            }
            
            return false;
        }

        protected bool GetNeedQueue(PlayerDataAsyc pl)
        {
            if (pl.queuetime >= maxqueueTime)
            {
                return true;
            }
            
            float rate = ServerConfigManager.Instance.GetQueueRoboRate(ting.RealCnt);
            //Debug.Info($"排队成的概率:{rate},{ting.RealCnt}");
            return BaseFun.random.NextDouble() < rate;
        }
    }
}