using System;
using System.Collections.Generic;
using System.Net;
using GameMessage;
using MrWu.Debug;
using Server.Config;
using Server.Core;
using GameConfig = Server.Config.GameConfig;

namespace Server
{
    public class ServerConfigManager : SingleInstance<ServerConfigManager>
    {
        #region 服务器配置
        /// <summary>
        /// 节点配置
        /// </summary>
        public NodeConfig NodeConfig
        {
            get;
            private set;
        }

        /// <summary>
        /// 节点Id
        /// </summary>
        public byte NodeId => NodeConfig.NodeId;

        /// <summary>
        /// 节点编号
        /// </summary>
        public byte NodeNum => NodeConfig.NodeNum;

        /// <summary>
        /// 服务器名称
        /// </summary>
        public string ServerName => NodeConfig.ServerName;

        public int MaxVer => NodeConfig.MaxVer;
        
        public int MinVer => NodeConfig.MinVer;
        
        public int MaxCVer => NodeConfig.MaxCVer;
        
        public int MinCVer => NodeConfig.MinCVer;

        public int UpdateServerInfoTime => 5;
        
        public int WebSocketPort => NodeConfig.WebSocketPort;
        
        public int OnTime => NodeConfig.OnTime;
        
        public IPEndPoint InnerNetEndPoint
        {
            get;
            private set;
        }
        
        public IPEndPoint OuterNetEndPoint
        {
            get;
            private set;
        }

        #endregion

        private bool isInit = false;
        
        #region 游戏配置

        
        /// <summary>
        /// 游戏自身的配置, 有可能是空
        /// </summary>
        public GameConfig GameConfig
        {
            get;
            private set;
        }

        public int GameId => GameConfig.GameId;

        public int ClientId => GameConfig.ClientId;
        
        public string GameName => GameConfig.GameName;
        
        public byte GameMode => GameConfig.GameMode;
        
        public byte GameStyle => GameConfig.GameStyle;
        
        public byte OpenGold => GameConfig.OpenGold;
        
        public int GoldDeskWarTimeOut => GameConfig.GoldDeskWarTimeOut;
        
        public byte OpenFriend => GameConfig.OpenFriend;
        
        public int FriendDeskWarTimeOut => GameConfig.FriendDeskWarTimeOut;
        
        public int FriendStarWarTimeOut => GameConfig.FriendStarWarTimeOut;
        
        public int ClubReadyTimeOut => GameConfig.ClubReadyTimeOut;

        public int FriendAutoReady => GameConfig.FriendAutoReady;
        
        public float ClubBalance => GameConfig.ClubBalance;
        
        public string GameGz => GameConfig.GameGz;

        public int RobotMinMoney => 20000;

        public int RobotMaxMoney => 2000000;
        
        /// <summary>
        /// 厅的配置
        /// </summary>
        public TingConfig[] Tings
        {
            get;
            private set;
        }

        public int TingCnt
        {
            get;
            private set;
        }

        public CastlesConfig[] Castles
        {
            get;
            private set;
        }
        
        public int CastlesCnt
        {
            get;
            private set;
        }
        
        #endregion

        /// <summary>
        /// 排队参数
        /// </summary>
        private readonly List<QueueConfig> QueueConfigs = new List<QueueConfig>();
        
        public ServerGameConfig ServerGameConfig
        {
            get;
            private set;
        }

        /// <summary>
        /// 城堡的奖励数据
        /// </summary>
        public CastleRewardData CastleRewardData
        {
            get;
            private set;
        }

        /// <summary>
        /// 启动服务器就刷新配置, 后续可以在这个方法加个动态更新
        /// </summary>
        public void RefreshData()
        {
            try
            {
                if (isInit)
                {
                    return;
                }
                
                NodeConfig = NodeConfigCategory.Instance.GetSelfConfig();
                InnerNetEndPoint = new IPEndPoint(IPAddress.Parse(NodeConfig.InnerHost), NodeConfig.InnerNetPort);
                if (NodeConfig.OuterNetPort > 0)
                {
                    OuterNetEndPoint = new IPEndPoint(IPAddress.Parse(NodeConfig.InnerHost), NodeConfig.OuterNetPort);
                }
                
                if (GameConfigCategory.Instance.Contain(NodeConfig.Id))
                {
                    GameConfig = GameConfigCategory.Instance.Get(NodeConfig.Id);
                    Tings = TingConfigCategory.Instance.GetTings(GameConfig.GameId);
                    TingCnt = Tings.Length;
                    Castles = CastlesConfigCategory.Instance.GetCastlesConfig(GameConfig.GameId);
                    CastlesCnt = Castles.Length;
                    bool hasCastleReward = false;

                    ServerGameConfig = new ServerGameConfig
                    {
                        ServerGameId = GameConfig.GameId,
                        ClientGameId = GameConfig.ClientId,
                        CastleConfigs = new GameCastleConfig[CastlesCnt],
                        TingConfigs = new GameTingConfig[TingCnt]
                    };

                    if (GameConfig.OpenFriend > 0)
                    {
                        if (GameConfig.OpenGold > 0)
                        {
                            ServerGameConfig.OpenMode = 2;
                        }
                        else
                        {
                            ServerGameConfig.OpenMode = 1;
                        }
                    }
                    
                    for (int i = 0; i < CastlesCnt; i++)
                    {
                        var config = Castles[i];
                        ServerGameConfig.CastleConfigs[i] = new GameCastleConfig
                        {
                            Id = config.CastleId,
                            TingIds = config.Tings,
                            BeiLv = config.BeiLv,
                            Tax = config.Tax,
                            Exp = config.Exp,
                            MinMoney = config.MinMoney,
                            MaxMoney = config.MaxMoney,
                            IsFriend = GameConfig.OpenFriend > 0 && i == CastlesCnt - 1
                        };

                        if (config.CanSaiJuanReward > 0)
                        {
                            hasCastleReward = true;
                        }
                    }

                    for (int i = 0; i < TingCnt; i++)
                    {
                        var config = Tings[i];
                        ServerGameConfig.TingConfigs[i] = new GameTingConfig
                        {
                            Id = config.TingId,
                            Name = config.TingName,
                            MinPlayerCnt = config.MinPlayerCnt,
                            MaxPlayerCnt = config.MaxPlayerCnt,
                            CastleIds = null,
                            IsFriend = GameConfig.OpenFriend > 0 && i == TingCnt - 1
                        };
                    }

                    Debug.Info($"RefreshData:{TingCnt} {CastlesCnt}");

                    //最后一个房间 max 改成 0
                    for (int i = CastlesCnt - 1; i >= 0; i--)
                    {
                        if (ServerGameConfig.CastleConfigs[i].IsFriend)
                        {
                            ServerGameConfig.CastleConfigs[i].MaxMoney = 0;
                        }
                        else
                        {
                            ServerGameConfig.CastleConfigs[i].MaxMoney = 0;
                            break;
                        }
                    }

                    if (hasCastleReward)
                    {
                        CastleRewardData = new CastleRewardData();
                        CastleRewardData.Reward = new CastleReward[CastlesCnt];

                        for (int i = 0; i < CastlesCnt; i++)
                        {
                            CastleReward rew = new CastleReward();
                            rew.CastleId = Castles[i].CastleId;

                            rew.Reward = new GameMessage.GameRewardResData[1];
                            rew.Reward[0] = new GameMessage.GameRewardResData()
                            {
                                Count = Castles[i].CanSaiJuanReward
                            };
                            CastleRewardData.Reward[i] = rew;
                        }
                    }

                    QueueConfigs.Clear();
                    for (int i = 0; i < QueueConfigCategory.Instance.DataList.Count; i++)
                    {
                        if (QueueConfigCategory.Instance.DataList[i].GameId == GameConfig.GameId)
                        {
                            QueueConfigs.Add(QueueConfigCategory.Instance.DataList[i]);
                        }
                    }
                    
                    //排序
                    for (int i = 0; i < QueueConfigs.Count; i++)
                    {
                        int maxIdx = i;
                        for (int j = i+1; j < QueueConfigs.Count; j++)
                        {
                            if (QueueConfigs[j].PlayerCnt > QueueConfigs[maxIdx].PlayerCnt)
                            {
                                maxIdx = j;
                            }
                        }

                        if (maxIdx != i)
                        {
                            (QueueConfigs[i], QueueConfigs[maxIdx]) = (QueueConfigs[maxIdx], QueueConfigs[i]);
                        }
                    }
                }

                isInit = true;
                //
            }
            catch (Exception e)
            {
                Debug.Error($"配置出错:{e.Message} {e.StackTrace}");
            }
        }
        
        public float GetQueueRoboRate(int playerCnt)
        {
            for (int i = 0; i < QueueConfigs.Count; i++)
            {
                if (playerCnt >= QueueConfigs[i].PlayerCnt)
                {
                    return QueueConfigs[i].MergeRobotProb;
                }
            }

            return 0.05f;
        }
    }
}