/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2018-11-16
 * 时间: 9:27
 *
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */

using System;
using Server.Pack;
using System.Collections;
using System.Collections.Generic;
using MrWu.Debug;
using Server.Data;
using System.Text;
using System.Threading;
using GameData;
using Game.Robot;
using GameMessage;
using Server.Core;

namespace Server
{
    /// <summary>
    /// 厅管理
    /// </summary>
    public abstract class TingManager : IGameUtil, ICollection<Desk>, IGameMessage<GamePack>
    {
        /*
         * 所有的桌子
         * 闲置的桌子
         * 排队的桌子
         * 开战中的桌子
         *
         * 有玩家来排队时创建桌子desk
         * 把desk添加至排队中的桌子列表
         *
         * 当桌子开战时，告诉厅管理从闲置的桌子中移除桌子 把桌子添加至 开战中的桌子
         *
         * 当玩家退出桌子时，检查桌子是不是只有机器人
         * 如果是，清空桌子，把桌子添加到闲置的桌子列表
         *
         * 当桌子战斗结束时，告诉厅管理从开战中的桌子放置排队中的桌子列表 如果真人没满，把里面的真人尽量往别的桌子凑
         * (前提是去别的桌子后比现在的桌子人多)
         * 查看玩家连续赢的次数，在一桌连续赢了超过5局，则换房间
         *
         * 桌子不清楚
         *
         * */

        #region ICollection

        /// <summary>
        /// 桌子数量
        /// </summary>
        public int Count
        {
            get { return desks.Count; }
        }

        /// <summary>
        /// 是否是只读
        /// </summary>
        public bool IsReadOnly
        {
            get { return true; }
        }


        void ICollection<Desk>.Add(Desk item)
        {
        }

        void ICollection<Desk>.Clear()
        {
        }

        /// <summary>
        /// 是否存在某个桌子
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(Desk item)
        {
            if (item == null)
                return false;
            return item.id >= 0 && item.id < Count;
        }

        void ICollection<Desk>.CopyTo(Desk[] array, int arrayIndex)
        {
            desks.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        bool ICollection<Desk>.Remove(Desk item)
        {
            return false;
        }

        /// <summary>
        /// 迭代器
        /// </summary>
        /// <returns></returns>
        public IEnumerator<Desk> GetEnumerator()
        {
            return desks.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// 桌子
        /// </summary>
        /// <param name="idx"></param>
        /// <returns></returns>
        public Desk this[int idx]
        {
            get { return desks[idx]; }
        }

        /// <summary>
        /// 是否要动态回收桌子
        /// </summary>
        protected virtual bool isRecycle
        {
            get { return true; }
        }

        #endregion

        #region 统计

        /// <summary>
        /// 战斗次数
        /// </summary>
        public int warCnt;

        /// <summary>
        /// 总战斗时间
        /// </summary>
        public long totalwarTime;

        /// <summary>
        /// 平均战斗时间
        /// </summary>
        public long avgWarTime
        {
            get
            {
                if (warCnt == 0)
                    return 0;
                return totalwarTime / warCnt;
            }
        }

        /// <summary>
        /// 最大开战时间
        /// </summary>
        public long maxWarTime;

        /// <summary>
        /// 最短开战时间
        /// </summary>
        public long minWarTime = long.MaxValue;

        /// <summary>
        /// 玩家的数量
        /// </summary>
        public int PlayerCnt;

        /// <summary>
        /// 机器人数量
        /// </summary>
        public int RobotCnt;

        /// <summary>
        /// 真人数量
        /// </summary>
        public int RealCnt;

        /// <summary>
        /// 机器人胜利次数
        /// </summary>
        public int robotWinCnt;

        #endregion

        /// <summary>
        /// 厅配置
        /// </summary>
        public readonly Server.Config.TingConfig config;

        /// <summary>
        /// 所有的房间
        /// </summary>
        public readonly IList<Desk> desks = new List<Desk>();

        #region 闲置的桌子

        /// <summary>
        /// 闲置的桌子数量
        /// </summary>
        public int IdleCount
        {
            get { return idle.Count; }
        }

        /// <summary>
        /// 闲置的桌子
        /// </summary>
        protected readonly IList<Desk> idle = new List<Desk>();

        /// <summary>
        /// 添加到闲置的桌子
        /// </summary>
        public void AddIdleing(Desk desk)
        {
            if ((desk.state & DeskState.Queue) > 0)
                RemoveQueue(desk);
            if ((desk.state & DeskState.War) > 0)
                RemoveWaring(desk);

            //闲置的桌子没有其他状态
            desk.state = DeskState.Idle | desk.state;
            idle.Add(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("AddIdleing Id of Same");
            }
            else
            {
                Debug.Error("AddIdleing Error Thread is not Same!");
            }
        }

        /// <summary>
        /// 移除闲置的桌子
        /// </summary>
        /// <param name="desk"></param>
        /// <returns></returns>
        public bool RemoveIdle(Desk desk)
        {
            bool r = idle.Remove(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("RemoveIdle Id of Same");
            }
            else
            {
                Debug.Error("RemoveIdle Error Thread is not Same!");
            }

            if (r)
                desk.state = desk.state & ~DeskState.Idle;
            return r;
        }

        #endregion

        #region 排队的桌子

        /// <summary>
        /// 排队桌子的数量
        /// </summary>
        public int QueueCount
        {
            get { return queueing.Count; }
        }

        /// <summary>
        /// 排队中的桌子
        /// </summary>
        public readonly IList<Desk> queueing = new List<Desk>();

        /// <summary>
        /// 添加到排队中的桌子队列
        /// </summary>
        public void AddQueueing(Desk desk)
        {
            desk.state = DeskState.Queue | desk.state;
            queueing.Add(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("AddQueueing Id of Same");
            }
            else
            {
                Debug.Error("AddQueueing Error Thread is not Same!");
            }
        }

        /// <summary>
        /// 移除排队中的桌子
        /// </summary>
        /// <param name="desk"></param>
        /// <returns></returns>
        public bool RemoveQueue(Desk desk)
        {
            bool r = queueing.Remove(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("RemoveQueue Id of Same");
            }
            else
            {
                Debug.Error("RemoveQueue Error Thread is not Same!");
            }

            if (r)
                desk.state = desk.state & ~DeskState.Queue;
            return r;
        }

        #endregion

        #region 开战的桌子

        /// <summary>
        /// 开战的桌子数量
        /// </summary>
        public virtual int WarCount
        {
            get { return waring.Count; }
        }

        /// <summary>
        /// 战斗中的
        /// </summary>
        protected readonly IList<Desk> waring = new List<Desk>();

        /// <summary>
        /// 添加到战斗中的桌子
        /// </summary>
        /// <param name="desk"></param>
        public void AddWaring(Desk desk)
        {
            waring.Add(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("AddWaring Id of Same");
            }
            else
            {
                Debug.Error("AddWaring Error Thread is not Same!");
            }

            desk.state = DeskState.War | desk.state;
        }

        /// <summary>
        /// 移除战斗中的桌子
        /// </summary>
        /// <param name="desk"></param>
        /// <returns></returns>
        public bool RemoveWaring(Desk desk)
        {
            bool r = waring.Remove(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("RemoveWaring Id of Same");
            }
            else
            {
                Debug.Error("RemoveWaring Error Thread is not Same!");
            }

            if (r)
                desk.state = desk.state & ~DeskState.War;
            return r;
        }

        #endregion

        /// <summary>
        /// 游戏模式
        /// </summary>
        public int gameMode
        {
            get { return ServerConfigManager.Instance.GameMode; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="config"></param>
        public TingManager(Server.Config.TingConfig config)
        {
            this.config = config;
            int len = config.DeskCnt;
            for (int i = 0; i < len; i++)
            {
                CreateNewDesk();
            }
        }

        #region IGameWinMoney

        /// <summary>
        /// 赢的游戏币
        /// </summary>
        public Int64 winmoney { get; private set; }

        /// <summary>
        /// 税收的钱
        /// </summary>
        public Int64 taxmoney { get; private set; }

        /// <summary>
        /// 添加赢的游戏币
        /// </summary>
        /// <param name="money"></param>
        public void AddWinMoney(long money)
        {
            // Debug.Warning("赢取的金额:" + money);

            winmoney += money;
        }

        /// <summary>
        /// 添加税收的钱
        /// </summary>
        /// <param name="money"></param>
        public void AddTaxMoney(long money)
        {
            //  Debug.Warning("税收增加:" + money);

            taxmoney += money;
        }

        #endregion

        /// <summary>
        /// 有玩家退出桌子
        /// </summary>
        public abstract bool QuitDesk(PlayerDataAsyc pl, bool isSendPack);

        #region 获取桌子

        /// <summary>
        /// 获取桌子
        /// </summary>
        /// <param name="deskstate">要的桌子状态,一般来说,不会获取开战的桌子</param>
        /// <param name="deskinfo">桌子信息</param>
        /// <returns></returns>
        public virtual Desk GetDesk(DeskState deskstate = DeskState.Queue | DeskState.Idle, DeskInfo deskinfo = null)
        {
            Desk desk = null;

            //要排队的，优先获取排队的
            if ((deskstate & DeskState.Queue) > 0)
            {
                //要排队的
                if (QueueCount > 0)
                    desk = queueing[0];
            }

            if (desk == null && (deskstate & DeskState.Idle) > 0)
            {
                //如果没拿到桌子,要闲置的
                if (IdleCount > 0)
                {
                    //有闲置的,直接获取闲置的
                    desk = idle[0];
                    if (deskinfo != null)
                    {
                        desk.SetDeskInfo(deskinfo);
                    }
                }

                if (desk == null)
                {
                    //还是没拿到   创建新桌子
                    desk = CreateNewDesk(deskinfo);
                }
            }

            return desk;
        }

        /// <summary>
        /// 创建一个新桌子
        /// </summary>
        /// <returns></returns>
        protected Desk CreateNewDesk(DeskInfo deskinfo = null)
        {
            Desk desk = GameManager.instance.factory.CreateDesk(this, config, Count, deskinfo);
            desk.WarOverHandler += DeskWarOver;
            desk.PlayerChangeHandler += PlayerChange;
            desks.Add(desk);

            if (Thread.CurrentThread.ManagedThreadId == ServerConst.MainThreadId)
            {
                Debug.Info("CreateNewDesk Id of Same");
            }
            else
            {
                Debug.Error("CreateNewDesk Error Thread is not Same!");
            }

            AddIdleing(desk); //刚创建的桌子
            return desk;
        }

        /// <summary>
        /// 根据桌号获取指定桌子
        /// </summary>
        /// <param name="deskid"></param>
        /// <returns></returns>
        public virtual Desk GetDeskByDeskId(int deskid)
        {
            return null;
        }

        #endregion

        /// <summary>
        /// 战斗结束
        /// </summary>
        /// <param name="warTime"></param>
        protected void DeskWarOver(DateTime warTime)
        {
            long tmp = (long)(DateTime.Now - warTime).TotalSeconds;

            warCnt++;

            //总战斗时间
            totalwarTime = totalwarTime + tmp;
            if (tmp < minWarTime)
                minWarTime = tmp;
            if (tmp > maxWarTime)
                maxWarTime = tmp;
        }

        /// <summary>
        /// 用户数量变化
        /// </summary>
        /// <param name="cnt"></param>
        /// <param name="isRobot"></param>
        protected void PlayerChange(int cnt, bool isRobot)
        {
            PlayerCnt += cnt;
            if (isRobot)
                RobotCnt += cnt;
            else
                RealCnt += cnt;
        }

        /// <summary>
        /// 进入厅
        /// </summary>
        public abstract bool InTing(PlayerDataAsyc pl, int roomid, ref string errinfo, ref int errorcode, int deskid = -1, string pwd = "",
            bool isClub = false);

        #region ITimerProcessor

        /// <summary>
        /// 定时器
        /// </summary>
        public virtual void OnTime(int Interval)
        {
            //先检查朋友房的厅中，是否有朋友房桌子需要解散的, --- 自动解散掉
            int len = desks.Count;
            for (int i = len - 1; i >= 0; i--)
            {
                desks[i].OnTime(Interval);
            }
        }

        /// <summary>
        /// 定时器处理
        /// </summary>
        public abstract void SecondTime();

        #endregion

        /// <summary>
        /// 是否存在某个桌子
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool isExists(int id)
        {
            return id >= 0 && id < Count;
        }

        #region IGameUtil

        /// <summary>
        /// 厅id
        /// </summary>
        public int id
        {
            get { return config.TingId; }
        }

        /// <summary>
        /// 是否是朋友房
        /// </summary>
        public abstract bool isFriend { get; }

        /// <summary>
        /// 初始化
        /// </summary>
        public virtual void Init()
        {
            foreach (var it in desks)
            {
                it.Init();
            }
        }

        /// <summary>
        /// 获取厅信息
        /// </summary>
        /// <param name="lx">字段类型</param>
        /// <returns>-1表示无效</returns>
        public virtual int GetIntValue(string lx)
        {
            switch (lx)
            {
                case "0": //桌子数量 0表示动态生成桌子  >0表示预先生成桌子!
                    if (config.DeskCnt <= 0)
                        return 0;
                    return config.DeskCnt;
                case "1": //最小开战人数
                    return config.MinPlayerCnt;
                case "2": //最大开战人数
                    return config.MaxPlayerCnt;
                case "3": //游戏模式
                    Debug.Error("转至游戏配置!");
                    break;
                case "4": //获取厅的输赢
                    int money = (int)(winmoney / 100);
                    Debug.Log("获取厅赢的钱:" + money);
                    return money;

                default:
                    Debug.Error("为解析的厅信息:" + lx);
                    break;
            }

            return -1;
        }

        /// <summary>
        /// 获取厅字符串信息
        /// </summary>
        /// <param name="lx">字段类型 0:获取厅的所有规则</param>
        /// <returns></returns>
        public virtual string GetStringValue(string lx)
        {
            switch (lx)
            {
                case "0": //获取厅的所有规则
                    return config.TingGz;
            }

            Debug.Warning("没有啥厅字符串信息" + lx);
            return string.Empty;
        }

        /// <summary>
        /// 获取厅数据
        /// </summary>
        /// <returns></returns>
        public virtual object GetData(string tag)
        {
            return null;
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pl"></param>
        public abstract void Ready(PlayerDataAsyc pl);

        /// <summary>
        /// 使用记牌器
        /// </summary>
        /// <param name="pl"></param>
        public virtual void UsingHandTracker(PlayerDataAsyc pl, UsingHandTrackerData pack)
        {
            if (pl.deskid < 0 || pl.deskid >= Count)
            {
                Debug.Warning("没有这个桌子!");
                return;
            }

            Debug.Info("使用记牌器!");
            desks[pl.deskid].UsingHandTracker(pl, pack);
        }

        #region IGameMessage

        /// <summary>
        /// 处理子游戏包
        /// </summary>
        /// <param name="pack"></param>
        public virtual void DoZyxPack(GamePack pack)
        {
            if (pack.pl.deskid < 0 || pack.pl.deskid >= desks.Count || pack.pl.seat < 0)
            {
                Debug.Warning("userid :" + pack.pl.userid + ",deskid:" + pack.pl.deskid + ",seat:" + pack.pl.seat);
                return;
            }

            desks[pack.pl.deskid].DoZyxPack(pack);
        }

        /// <summary>
        /// 处理聊天包
        /// </summary>
        /// <param name="pack"></param>
        public virtual bool DoChatPack(GamePack pack)
        {
            if (pack.pl.deskid < 0 || pack.pl.deskid >= desks.Count || pack.pl.seat < 0)
            {
                Debug.Warning("DoChatPack userid:" + pack.pl.userid + ",deskid:" + pack.pl.deskid + ",seat:" +
                              pack.pl.seat);
                return false;
            }

            return desks[pack.pl.deskid].DoChatPack(pack);
        }

        /// <summary>
        /// 处理道具包
        /// </summary>
        /// <param name="pack"></param>
        public virtual bool Drops(GamePack pack)
        {
            if (pack.pl.deskid < 0 || pack.pl.deskid >= desks.Count || pack.pl.seat < 0)
            {
                Debug.Warning("Drops userid:" + pack.pl.userid + ",deskid:" + pack.pl.deskid + ",seat:" + pack.pl.seat);
                return false;
            }

            return desks[pack.pl.deskid].DoProps(pack);
        }

        #endregion

        /// <summary>
        /// 重连
        /// </summary>
        /// <param name="deskid"></param>
        /// <param name="seat"></param>
        public virtual void Reconnect(int deskid, int seat)
        {
            if (deskid < 0 || deskid >= desks.Count)
            {
                Debug.Warning("deskid :" + deskid + ",count:" + desks.Count);
                return;
            }

            desks[deskid].Reconnect(seat);
        }

        /// <summary>
        /// 检查两个玩家的之间的作弊等级
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="other"></param>
        public virtual Tuple<int, int> CheckCheatingLevel(PlayerDataAsyc pl, PlayerDataAsyc other)
        {
            int myLevel = 0;
            int otherLevel = other.device.zuobichengdu;
            if (pl.device.GetPosition().isEmpty)
            {
                //无法定位
                myLevel = 1;
            }

            //计算距离
            //100米 内 高  500米内 中  1000米内 低
            double distance = WorldPosition.GetDistance(pl.device.GetPosition(), other.device.GetPosition());

            if (distance <= 50)
            {
                myLevel = 4;
                if (otherLevel < myLevel)
                    otherLevel = myLevel;
            }
            else if (distance <= 500)
            {
                myLevel = 3;
                if (otherLevel < myLevel)
                    otherLevel = myLevel;
            }
            else if (distance <= 1000)
            {
                myLevel = 2;
                if (otherLevel < myLevel)
                    otherLevel = myLevel;
            }

            if (!string.IsNullOrEmpty(pl.device.wifimac) && !string.IsNullOrEmpty(other.device.wifimac))
            {
                if (pl.device.wifimac == other.device.wifimac)
                {
                    //同一个wifi
                    myLevel = 4;
                    otherLevel = 4;
                }
            }

            // if (pl.ip == other.ip) {
            //     myLevel = 4;
            //     otherLevel = 4;
            // }
            //Debug.Log("计算距离:" + distance + "," + myLevel);
            return new Tuple<int, int>(myLevel, otherLevel);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("tingid:");
            sb.Append(id);
            sb.Append(Environment.NewLine);
            sb.Append("deskCnt:");
            sb.Append(this.Count);
            sb.Append(Environment.NewLine);
            sb.Append("是否朋友房:");
            sb.Append(this.isFriend);
            sb.Append(Environment.NewLine);
            sb.Append("机器人数量:");
            sb.Append(RobotController.instance.GetParCount(id));
            sb.Append(Environment.NewLine);
            sb.Append("税钱:");
            sb.Append(this.taxmoney);
            sb.Append(Environment.NewLine);
            sb.Append("赢的游戏:");
            sb.Append(this.winmoney);
            sb.Append(Environment.NewLine);
            sb.Append("总桌子:");
            sb.Append(this.desks.Count + "," + this.Count);
            sb.Append(Environment.NewLine);
            sb.Append("闲置的桌子:");
            sb.Append(this.IdleCount);
            sb.Append(Environment.NewLine);
            sb.Append("开战的桌子:");
            sb.Append(this.WarCount);
            sb.Append(Environment.NewLine);
            sb.Append("排队中的桌子:");
            sb.Append(this.QueueCount);
            sb.Append(Environment.NewLine);
            return sb.ToString();
        }

        public virtual void Close()
        {
            for (int i = 0; i < desks.Count; i++)
            {
                if (desks[i] != null)
                {
                    desks[i].Close();
                }
            }
        }
    }
}