using System;
using System.Text;
using Server.MQ;
using MrWu.Debug;
using Server.Pack;
using Server.Data.Module;
using GameData;
using Server.Config;

namespace Server
{
    public partial class GlobalManager
    {
        /// <summary>
        /// 消息处理器
        /// </summary>
        public class MessageProcessor
        {
            private GlobalManager instance
            {
                get { return GlobalManager.instance; }
            }

            /// <summary>
            /// 处理包的数量
            /// </summary>
            public long dopackCnt { get; protected set; }

            private long DopackRunKey = 0;
            
            /// <summary>
            /// 消息处理
            /// </summary>
            public void Run(StringBuilder logs)
            {
                int cnt = GlobalMQ.instance.GteMessageCnt();
                int dealCnt = 0;
                while (dealCnt < cnt)
                {
                    if (dealCnt > 500)
                    {
                        Debug.Error("处理的包太多");
                        break;
                    }

                    dealCnt++;
                    var msg = GlobalMQ.instance.GetMessage();
                    if (msg == null)
                    {
                        break;
                    }

                    if (TestValue.IsPrintLog)
                    {
                        DopackRunKey = Debug.StartTiming();
                    }
                    DoMessage(msg, logs);
                    if (!msg.isAdd && msg.AutoAck) //不循环处理 并且不是梳理完自动确认
                        WaitBeMsgPool.PutWaiteBeMsg(ref msg);

                    if (DopackRunKey > 0)
                    {
                        double runtime = Debug.GetRunTime(DopackRunKey);
                        DopackRunKey = 0;
                        if (runtime > 1000)
                        {
                            Debug.ImportantLog($"DoMessage 慢:{runtime}");
                        }
                    }
                }
            }


            /// <summary>
            /// 处理包
            /// </summary>
            protected void DoMessage(WaitBeMsg wbm, StringBuilder logStringBuilder)
            {
                dopackCnt++;

#if DEBUG
                var key = Debug.StartTiming();
#endif
                try
                {
                    wbm.isAdd = false;
                    if (wbm.head.packlx < 0)
                    {
#if DEBUG
                        logStringBuilder.AppendLine($"DoPackBase begin, packlx: {wbm.head.packlx}");
#endif
                        DoPackBase(wbm, logStringBuilder);
                    }
                    else
                    {
#if DEBUG
                        logStringBuilder.AppendLine($"DoPack begin, packlx: {wbm.head.packlx}");
#endif
                        DoPack(wbm, logStringBuilder);
                    }
                }
                catch (Exception e)
                {
#if DEBUG
                    logStringBuilder.AppendLine($"DoMessage Exception: {e}");
#endif
                    Debug.Error("处理吧包发生错误!" + e.ToString());
                    wbm.Ack();
                    return;
                }
                finally
                {
#if DEBUG
                    logStringBuilder.AppendLine($"finally, time: {Debug.GetRunTime(key)}");
#endif
                }

                if (wbm.isAdd)
                    GlobalMQ.instance.AddMessage(wbm);
                else
                {
                    if (wbm.AutoAck && !wbm.noAck && !wbm.isAck && wbm.deliveryTag > 0)
                        wbm.Ack();
                }
                //Debug.Info("直到处理用的时间:" + (DateTime.Now - wbm.logTime).TotalMilliseconds);
            }

            /// <summary>
            /// 服务器基本消息_分发处理
            /// </summary>
            /// <param name="msg"></param>
            /// <param name="logStringBuilder"></param>
            /// <returns></returns>
            protected virtual bool DoPackBase(WaitBeMsg msg, StringBuilder logStringBuilder)
            {
                switch (msg.head.packlx)
                {
                    case ServerPackAgreement.command:
                        instance.DoCommand(msg);
                        break;
                    case ServerPackAgreement.nodeHeart: //节点心跳
                        instance.Heart(msg);
                        break;
                    case ServerPackAgreement.openNode: //节点开启
                        instance.RecvOpenNode(msg);
                        break;
                    case ServerPackAgreement.closeNode: //节点正常关闭
                        instance.RecvCloseNode(msg);
                        break;

                    case ServerPackAgreement.KillMe: //关闭自身 -只能发一个包
                        instance.isKill = true;
                        break;
                    case ServerPackAgreement.NoStartWar: //禁止开战
                        Debug.Info("接收到禁止开战包!");
                        instance.IsCanWar = false;
                        break;
                    case ServerPackAgreement.CacheChange:
                        Debug.Info("接收到缓存变化包!");
                        instance.CacheChange(msg);
                        break;

                    case ServerPackAgreement.Ping:
                        instance.Ping(msg.head, msg.jsondata);
                        break;

                    case ServerPackAgreement.Pong:
                        instance.Pong(msg.head, msg.jsondata);
                        break;
                    case ServerPackAgreement.ModuleDie: //模块检测死亡包
                        instance.ModuleDie(msg);
                        break;

                    case ServerPackAgreement.PackTest: //包测试
                        break;

                    case ServerPackAgreement.ReportPlayerOnLineDataReq:
                        instance.ReportPlayerOnLineData(msg);
                        break;

                    default:
                        return instance.HandleOtherServerPack(msg); // false;
                }

                return true;
            }

            /// <summary>
            /// 处理模块包裹
            /// </summary>
            /// <param name="msg">路由</param>
            /// <param name="logStringBuilder"></param>
            protected virtual void DoPack(WaitBeMsg msg, StringBuilder logStringBuilder)
            {
                if (!CheckClientVer(msg.head))
                    return;
            }

            /// <summary>
            /// 检查客户端版本
            /// </summary>
            /// <param name="head"></param>
            protected virtual bool CheckClientVer(PackHead head)
            {
                if (head.packlx != GamePackAgreement.TransFerHttp &&
                    head.packlx != GamePackAgreement.TransFerPack &&
                    head.clientVer < ServerConfigManager.Instance.MinCVer)
                {
                    head.transfer = GamePackAgreement.MandatoryUpdate;
                    var md = head.Util;
                    if (md == null)
                        return true;

                    if (md.id == (int)ModuleType.HttpModule)
                        head.packlx = ServerPackAgreement.TransFerHttp;
                    else
                        head.packlx = ServerPackAgreement.TransFerPack;
                    GlobalMQ.instance.DeliveryOne(md, GlobalMQ.CreateMessage(head), true);
                    return false;
                }

                return true;
            }
        }
    }
}