using GameData;
using MrWu.Debug;
using Server.AliyunSDK.Logic;
using Server.Data;
using System;
using System.Collections.Generic;
using System.Text;
using GameMessage;
using MrWu.Basic;

namespace Server
{
    /// <summary>
    /// 金币场桌子
    /// </summary>
    public partial class Desk_gold : Desk
    {
        /// <summary>
        /// 是否是朋友房
        /// </summary>
        public override bool isFriend => false;

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="ting"></param>
        /// <param name="tingConfig"></param>
        /// <param name="id"></param>
        /// <param name="info"></param>
        public Desk_gold(TingManager ting, Server.Config.TingConfig tingConfig, int id, DeskInfo info = null) : base(ting, tingConfig,
            id, info)
        {
        }

        /// <summary>
        /// 桌子上添加玩家
        /// </summary>
        /// <param name="pl">玩家</param>
        /// <param name="roomid">房间id</param>
        /// <returns></returns>
        protected override int AddPlayerArray(PlayerDataAsyc pl, int roomid)
        {
            int seat = -1;
            int len = Count;
            for (int i = 0; i < len; i++)
            {
                if (pls[i] != null && pls[i].userid == pl.userid)
                {
                    Debug.Error("桌上有相同玩家:" + pl.userid);
                    return seat;
                }

                if (pls[i] == null)
                {
                    PlayerChange(pl, false);

                    if (!GameManager.instance.SetPlayerShadow(pl, roomid)) //2020/02/22 增加 判断，没获取到影子就跳走
                        return seat;

                    if (gameMode == 1 && pl.isRobot)
                    {
                        pl.nickname = pl.shadows[0].nickname;
                    }

                    pls[i] = pl;
                    seat = i;
                    pl.DepositChange = PlayerDepositChange;
                    break;
                }
            }

            return seat;
        }

        /// <summary>
        /// 添加玩家
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="roomid"></param>
        /// <returns></returns>
        public override bool AddPlayer(PlayerDataAsyc pl, int roomid)
        {
            StringBuilder logStringBuilder = new StringBuilder();

            try
            {
                if (PlayerCnt >= tingConfig.MaxPlayerCnt)
                {
                    Debug.Error("玩家数量超过最大值!" + PlayerCnt + "," + id + "," + state);
                    return false;
                }

                long key1 = Debug.StartTiming();
                pl.seat = AddPlayerArray(pl, roomid);

                //Debug.Info("玩家上桌:" + pl.seat + ",userid:" + pl.userid);

                logStringBuilder.AppendLine("AddPlayerArray time:" + Debug.GetRunTime(key1));

                if (pl.seat < 0)
                {
                    Debug.Error("程序错误,上桌失败!");
                    return false;
                }

                //在桌上
                pl.state = (int)PlayerState.Desk;
                pl.SetDeposit(false);
                pl.tingid = tingConfig.TingId;
                pl.deskid = id;

                if (roomid < 0)
                { //如果是机器人，则自动获取房间id
                    //如果是机器人，则自动获取房间id
                    if (!pl.isRobot)
                        Debug.Error("程序错误,只有机器人排队才能传递小于0的值");

                    long key2 = Debug.StartTiming();

                    int len = pls.Length;
                    for (int i = 0; i < len; i++)
                    {
                        PlayerDataAsyc pda = pls[i];
                        if (pda == null)
                            continue;
                        if (!pda.isRobot)
                        {
                            pl.roomid = pda.roomid;
                        }
                    }

                    logStringBuilder.AppendLine("GetRoomid:" + Debug.GetRunTime(key2));
                }
                else
                    pl.roomid = roomid;

                RedressRobotMoney(pl);
                
                long key3 = Debug.StartTiming();
                if (!pl.isRobot && GameManager.instance.isExistsRoom(roomid))
                {
                    var room = GameManager.instance.FindRoom(roomid);
                    room.SetRoomPlayerCnt(pl);
                }

                logStringBuilder.AppendLine("SetRoomPlayerCnt  time:" + Debug.GetRunTime(key3));

                if (gameMode == 1)
                {
                    //百家乐，发送桌上玩家信息给客户端
                    //发送添加玩家包
                    SendAddPlayer(pl);
                    //发送所有玩家信息给玩家
                    SendAllPlayerInfo(pl);
                    //开战
                    pl.state = (int)PlayerState.War;
                }
                else
                {
                    //其他模式,发送自己信息给客户端 
                    long key4 = Debug.StartTiming();
                    SendAllPlayerInfo(pl, true);

                    logStringBuilder.AppendLine("SendAllPlayerInfo time:" + Debug.GetRunTime(key4));
                }

                long key5 = Debug.StartTiming();

                //发送场景切换
                GeneralSendPack.SendSceneChange(pl, SceneType.Desk);

                if ((state & DeskState.War) > 0)
                {
                    Debug.Error("进入桌子桌子正在开战!");
                    Reconnect(pl.seat);
                }

                logStringBuilder.AppendLine("SendPack time:" + Debug.GetRunTime(key5));

                return true;
            }
            finally
            {
                
            }
        }

        protected virtual void RedressRobotMoney(PlayerDataAsyc pl)
        {
            if (pl.isRobot)
            {
                RoomManager roomManager = GameManager.instance.FindRoom(pl.roomid);
                if (roomManager != null)
                {
                    if (pl.money < roomManager.config.MinMoney || pl.money > roomManager.config.MaxMoney)
                    {
                        if (roomManager.config.MinMoney < 10000)
                        {
                            pl.money = BaseFun.random.Next(roomManager.config.MinMoney, roomManager.config.MaxMoney);
                        }
                        else
                        {
                            int minValue = roomManager.config.MinMoney / 10000;
                            int maxValue = roomManager.config.MaxMoney / 10000;

                            pl.money = BaseFun.random.Next(minValue, maxValue) * 10000;
                        }
                        Debug.ImportantLog("纠正机器人身上的钱!");
                    }
                }
                else
                {
                    Debug.Error($"纠正机器人Money时，不存在房间:{pl.roomid}");
                }
            }
        }

        /// <summary>
        /// 从玩家列表中移除玩家
        /// </summary>
        /// <param name="pl"></param>
        /// <returns></returns>
        public override bool RemovePlayer(PlayerDataAsyc pl)
        {
            if ((state & DeskState.Idle) > 0)
            {
                return false;
            }

            PlayerDataAsyc tmppl;
            int len = Count;
            for (int i = 0; i < len; i++)
            {
                tmppl = pls[i];
                if (tmppl == null)
                    continue;
                if (pl.userid == tmppl.userid)
                {
                    pl.seat = -1;
                    pl.DepositChange = null;
                    pls[i] = null;
                    PlayerChange(pl, true);

                    Quit(i); //玩家退出事件

                    //设置玩家数量
                    SendRemovePlayer(i);
                    return true;
                }
            }

            return false;
        }

        bool strartWarError = false;


        /// <summary>
        /// 开战检查定时器
        /// </summary>
        protected void StartWarTimer()
        {
            if (gameMode == 1)
            { 
                //百家乐,有人就开战
                if ((state & DeskState.Idle) > 0)
                    return;
                if ((state & DeskState.War) == 0)
                { //未开战
                    //未开战
                    if (PlayerCnt > 0)
                    { 
                        //闲置 但是有人,开战
                        Debug.Info("游戏开战:" + this.id);
                        StartWar();
                    }
                }

                return;
            }
            else
            {
                //匹配模式,满人就开战 
                if ((state & DeskState.Queue) == 0)
                {
                    //状态不是排队，跳走
                    return;
                }

                PlayerDataAsyc tmppl;

                if (PlayerCnt >= ting.config.MinPlayerCnt)
                {
                    //大于最小可开战的人,全部自动准备
                    //Debug.Log("人到齐了，自动准备!");
                    int len = Count;
                    for (int i = 0; i < len; i++)
                    {
                        //全部自动准备
                        tmppl = pls[i];
                        if (tmppl == null)
                            continue;
                        Ready(tmppl, false); //--准备 自动准备,迎合原先的设计
                    }

                    //检查是否开战
                    bool war = true;
                    for (int i = len - 1; i >= 0; i--)
                    {
                        tmppl = pls[i];
                        if (tmppl == null)
                            continue;
                        if (tmppl.state != (int)PlayerState.Ready)
                        {
                            war = false;
                            if (!strartWarError)
                            {
                                Debug.Fatal("不该出现有人没准备的情况" + tmppl.ToString());
                                strartWarError = true;
                            }

                            break;
                        }
                    }

                    if (war)
                    {
                        //开战
                        StartWar();
                    }
                    else
                    {
                        Debug.Error("不应该存在的情况!");
                        ting.AddIdleing(this);
                    }
                }
            }
        }

        /// <summary>
        /// 检查战斗超时的定时器
        /// </summary>
        private int CheckWarTimeOutTimeCnt = 0;

        /// <summary>
        /// 检查战斗超时的时间间隔
        /// </summary>
        private const int DoCheckTimeOutInterval = 60;

        /// <summary>
        /// 战斗检查超时
        /// </summary>
        private void CheckWarTimeOutTimer()
        {
            if (gameMode == 1) //百家乐模式不检查
                return;

            if ((state & DeskState.War) == 0)
                return;

            CheckWarTimeOutTimeCnt++;

            if (CheckWarTimeOutTimeCnt < DoCheckTimeOutInterval)
            {
                return;
            }

            CheckWarTimeOutTimeCnt = 0;

            DateTime wartimeout = DateTime.Now.AddMinutes(-warTimeOut);

            //Debug.Error("检查桌子是否超时:" + warTime + "," + wartimeout);

            //检查是否超时
            if (warTime < wartimeout) //开战时间在超时之前
            {
                //先拿到所有的玩家
                List<PlayerDataAsyc> tmps = new List<PlayerDataAsyc>(pls);
                this.WarOver();
                if (gameLogic.TimeOutWarOver())
                {
                    int cnt = tmps.Count;
                    for (int i = cnt - 1; i >= 0; i--)
                    {
                        //循环所有的玩家在-在线的强制离线
                        if (tmps[i] != null && !tmps[i].isRobot)
                        {
                            Debug.Error("超时未打完!!!" + tmps[i].userid + "," + tmps[i].state + "," + tmps[i].id);
                            GameManager.instance.QuitGame(tmps[i], "CheckWarTimeOutTimer");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 金币场秒级定时器
        /// </summary>
        public override void SecondTime()
        {
            //金币场模式
            StartWarTimer();
            CheckWarTimeOutTimer();

            if ((state & DeskState.War) > 0)
            {
                PlayerDataAsyc tmppl;
                for (int i = Count - 1; i >= 0; i--)
                {
                    tmppl = pls[i];
                    if (tmppl == null)
                    {
                        continue;
                    }

                    if (!tmppl.isDePosit && tmppl.outline > 0)
                    {
                        tmppl.OutLineTime++;
                        if (tmppl.OutLineTime > 10)
                        {
                            GameManager.instance.DoTuoGuanCalc(tmppl, true);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 开战处理
        /// </summary>
        public override void StartWar()
        {
            if (!GlobalManager.instance.IsCanWar)
            {
                SendNoWarPack();
                return;
            }

            base.StartWar();

            CheckWarTimeOutTimeCnt = 0;

            if (gameMode != 1)
            {
                PlayerDataAsyc tmppl;
                int len = Count;
                for (int i = 0; i < len; i++)
                {
                    tmppl = pls[i];
                    if (tmppl == null)
                        continue;

                    if (!tmppl.isRobot)
                    {
                        // Debug.Error("开战发送全桌玩家信息:" + tmppl.userid);
                        SendAllPlayerInfo(tmppl);
                    }

                    tmppl.state = (int)PlayerState.War;
                    tmppl.WarMoney = 0;
                }
            }

            SendStartWar();
            gameLogic.StartWar();
        }


        /// <summary>
        /// 
        /// </summary>
        public override void WarOver()
        {
            //战斗结束 处理完, 
            // 桌子放入限制的桌子列表, 玩家状态全部在房间中, 客户端记录上次房间进入的厅，发送过来...
            // 人进入房间
            // 

            //要把人全部踢出桌子!

            /*
             * 1.修改房间状态
             * 2.修改厅中的列表
             * 3.处理玩家信息
             * 4.检查房间重新排队
             *
             * */

            try
            {
                SaveGoldRecordData();
            }
            catch (Exception e)
            {
                Debug.Error($"保存战绩出错:{e.Message}");
            }

            if (CalculateIsRobotWin())
            {
                ting.robotWinCnt++;
            }

            base.WarOver();

            GetOverHandle().WarOver();
            //发送结束信号
        }

        /// <summary>
        /// 计算是否机器人胜利
        /// </summary>
        private bool CalculateIsRobotWin()
        {
            long winMoney = 0;
            for (int i = 0; i < Count; i++)
            {
                if (pls[i] == null || !pls[i].isRobot)
                    continue;
                winMoney += pls[i].WarMoney;
            }
            return winMoney > 0;
        }

        protected WarOverHandle generalHandle;
        protected WarOverHandle baijialeHandle;

        protected virtual WarOverHandle GetOverHandle()
        {
            if (generalHandle == null)
                generalHandle = new GeneralWarOver(this);
            if (baijialeHandle == null)
                baijialeHandle = new BaiJiaLeWarOver(this);
            if (gameMode != 1)
                return generalHandle;
            return baijialeHandle;
        }

        /// <summary>
        /// 保存金币场战绩记录
        /// </summary>
        public void SaveGoldRecordData()
        {
            // 这里还要看影子数据 - 这样存下去就是真实数据
            // 分类 金币模式,比赛模式,朋友房模式    与回放数据绑定
            List<WarGoldRecordItemData> datas = new List<WarGoldRecordItemData>();
            List<WarRecordPlayerData> players = new List<WarRecordPlayerData>();

            for (int i = 0; i < Count; i++)
            {
                if (pls[i] == null || pls[i].isRobot || pls[i].MatchObj != null)
                    continue;

                players.Clear();
                for (int j = 0; j < Count; j++)
                {
                    pls[j].UpdateShadow(pls[i].roomid,IsMatchDesk && !pls[i].IsJoinMatch);
                    players.Add(new WarRecordPlayerData()
                    {
                        UserId = pls[j].userid, //这里有鬼的问题，后面把鬼的ID 头像固定化。不然显示要穿帮
                        Score = 0, //金币场暂时不存这个，这个现在统计不到
                    });
                }

                RoomManager roomManager = GameManager.instance.FindRoom(pls[i].roomid);
                Server.Config.CastlesConfig config = roomManager?.config;
                WarGoldRecordItemData data = new WarGoldRecordItemData();
                int shui = GameManager.instance.FindRoom(pls[i].roomid).config.Tax;
                data.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                data.GameId = ServerConfigManager.Instance.ClientId;
                data.UserId = pls[i].userid;
                data.Score = pls[i].WarMoney;
                data.Tax = shui;
                if (config != null)
                {
                    data.BeiLv = config.BeiLv;
                    data.Tax = config.Tax;
                }

                data.Content = players;
                datas.Add(data);
                Debug.Info($"上传玩家{pls[i].userid}金币场战绩数据");
            }

            if (datas.Count > 0)
            {
                WarRecordSLSManager.Instance.ReportGoldAsync(datas);
            }
        }

        /// <summary>
        /// 加载桌子
        /// </summary>
        /// <returns></returns>
        public override bool LoadDesk()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="seat"></param>
        /// <param name="lx"></param>
        /// <param name="num"></param>
        public override void IncMoney(int seat, int lx, int num)
        {
            return;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        public override void LoadMem(byte[] data, bool isOld)
        {
            Debug.Error("金币场不存在加载桌子内存！");
        }

        /// <summary>
        /// 战斗结束的处理
        /// </summary>
        protected interface WarOverHandle
        {
            /// <summary>
            /// 桌子
            /// </summary>
            Desk_gold desk { get; }

            /// <summary>
            /// 战斗结束
            /// </summary>
            void WarOver();
        }

        /// <summary>
        /// 普通游戏的战斗结束
        /// </summary>
        protected class GeneralWarOver : WarOverHandle
        {
            /// <summary>
            /// 桌子
            /// </summary>
            public Desk_gold desk { get; private set; }

            /// <summary>
            /// 构造器
            /// </summary>
            /// <param name="desk"></param>
            public GeneralWarOver(Desk_gold desk)
            {
                this.desk = desk;
            }

            /// <summary>
            /// 战斗结束处理
            /// </summary>
            public void WarOver()
            {
                Debug.Log("普通游戏战斗结束!!!!");
                //金币场超过上限检测在 进入桌子的时候

                if (!desk.ting.RemoveWaring(desk))
                {
                    Debug.Error("竟然没能移出桌子!");
                }

                bool isAllRobot = desk.RealPerson == 0;
                PlayerDataAsyc tmppl;
                int len = desk.Count;
                for (int i = len - 1; i >= 0; i--)
                {
                    tmppl = desk[i];
                    if (tmppl == null)
                        continue;

                    if (tmppl.state == (int)PlayerState.War)
                    {
                        tmppl.state = (int)PlayerState.Desk;
                    }
                    else
                    {
                        Debug.Error("不可能存在的情况asdasjbdkjasb!" + tmppl.state);
                        tmppl.state = (int)PlayerState.Desk;
                    }

                    if (tmppl.outline != 1)
                        desk.SendWarOver(tmppl);

                    if (!tmppl.isRobot) //玩家不是机器人-打完就退出桌子,此处会检查回收
                        desk.ting.QuitDesk(tmppl, false);
                    if (tmppl.outline == 1)
                    {
                        //Debug.Error("玩家已经离线，退出桌子处理:" + tmppl);

                        GameManager.instance.QuitGame(tmppl, "WarOver");
                    }
                }

                if (isAllRobot)
                {
                    for (int i = len - 1; i >= 0; i--)
                    {
                        tmppl = desk[i];
                        if (tmppl == null) continue;
                        desk.ting.QuitDesk(tmppl, false);
                    }

                    desk.ClearPlayer();
                }
            }
        }

        /// <summary>
        /// 百家乐战斗结束
        /// </summary>
        public class BaiJiaLeWarOver : WarOverHandle
        {
            /// <summary>
            /// 桌子
            /// </summary>
            public Desk_gold desk { get; private set; }

            /// <summary>
            /// 构造器
            /// </summary>
            /// <param name="desk"></param>
            public BaiJiaLeWarOver(Desk_gold desk)
            {
                this.desk = desk;
            }

            /// <summary>
            /// 战斗结束处理
            /// </summary>
            public void WarOver()
            {
                Debug.Info("百家乐战斗结束!!!!!!" + desk.id);

                //检查游戏币是否超过上限,超过则把玩家踢出去-让他手动去存金币
                int len = desk.Count;
                for (int i = len - 1; i >= 0; i--)
                {
                    if (desk[i] == null)
                        continue;

                    if (desk[i].money >= playerData.MaxMoney)
                    {
                        if (desk[i].isRobot)
                            desk[i].money -= 500000000;
                    }
                }

                if (desk.PlayerCnt == 0)
                {
                    if (desk.ting.RemoveWaring(desk))
                    {
                        Debug.Error("没有人的桌子移出开战列表却失败!");
                    }
                }
            }
        }
    }
}
