/*
 * 作者:吴隆健
 * 日期: 2019-04-16
 * 时间: 14:42
 * 
 */

using System;
using Server.Data.Module;
using GameData;
using Server.DB.Redis;
using System.Collections.Concurrent;

namespace Server {
    /// <summary>
    /// 路由管理
    /// </summary>
    public class RountingManager : ServerNode {
        /// <summary>
        /// 
        /// </summary>
		public static RountingManager instance { get; } = new RountingManager();


        /// <summary>
        /// 
        /// </summary>
        public string moduleName {
            get;
            private set;
        }

        /// <summary>
        /// 所有模块的名称_用来发送用的
        /// </summary>
        public readonly ConcurrentDictionary<int, string> moduleNames = new ConcurrentDictionary<int, string>();

        //------------------------------路由名称--------------------------------- 

        /// <summary>
        /// 系统群发路由
        /// </summary>
        public const string AllServerRouteName = "ServerAll";

        private string m_clubsterRouteName;
        /// <summary>
        /// 集群主路由-发给本模块都需要经过此路由器
        /// </summary>
        public string clubsterRouteName {
            get {
                if (m_clubsterRouteName == null)
                    m_clubsterRouteName = moduleName + "." + id;
                return m_clubsterRouteName;
            }
        }

        private string m_clusterAllRouteName;
        /// <summary>
        /// 集群群发路由-集群路由转发而来
        /// </summary>
        public string clusterAllRouteName {
            get {
                if (m_clusterAllRouteName == null)
                    m_clusterAllRouteName = clubsterRouteName + ".all";
                return m_clusterAllRouteName;
            }
        }

        private string m_clusterNodeOne;
        /// <summary>
        /// 集群单点路由
        /// </summary>
        public string clusterNodeOne {
            get {
                if (m_clusterNodeOne == null)
                    m_clusterNodeOne = clubsterRouteName + ".one";
                return m_clusterNodeOne;
            }
        }

        //-------------------------队列名称----------------------------------

        /// <summary>
        /// 群发所有的路由键
        /// </summary>
        public string routeallkey = "all";

        private string m_routeEveryOneKey;
        /// <summary>
        /// 发送给集群中的任意一个-这个通常谁处理都可以-升级时候有大用处-负载均衡
        /// </summary>
        public string routeEveryOneKey {
            get {
                if (m_routeEveryOneKey == null)
                    m_routeEveryOneKey = clubsterRouteName + ".everyOne";
                return m_routeEveryOneKey;
            }
        }

        private string m_nodeRouteKey;
        /// <summary>
        /// 路由到本模块队列的路由键
        /// </summary>
        public string nodeRouteKey {
            get {
                if (m_nodeRouteKey == null)
                    m_nodeRouteKey = clubsterRouteName + ".one." + nodeNum;
                return m_nodeRouteKey;
            }
        }

        private string m_nodeRouteMatch;
        /// <summary>
        /// 路由匹配键
        /// </summary>
        public string nodeRouteMatch {
            get {
                if (m_nodeRouteMatch == null) {
                    m_nodeRouteMatch = clubsterRouteName + ".one.*";
                }
                return m_nodeRouteMatch;
            }
        }

        //------------------------------队列名--------------------------

        private string m_queueEveryOne;
        /// <summary>
        /// 任意队列
        /// </summary>
        public string queueEveryOne {
            get {
                if (m_queueEveryOne == null) {
                    m_queueEveryOne = clubsterRouteName + ".everyOne";
                }
                return m_queueEveryOne;
            }
        }

        private string m_queueNode;
        /// <summary>
        /// 本节点的队列名
        /// </summary>
        public string queueNode {
            get {
                if (m_queueNode == null)
                    m_queueNode = clubsterRouteName + ".node." + nodeNum;
                return m_queueNode;
            }
        }

        //-----------------------------其他模块路由-----------------------

        private readonly ConcurrentDictionary<int, string> otherClusterRouteKey = new ConcurrentDictionary<int, string>();

        /// <summary>
        /// 获取某集群路由
        /// </summary>
        /// <param name="moduleId"></param>
        /// <returns></returns>
        public string GetClusterRoute(int moduleId) {
            string key = null;

            if (!otherClusterRouteKey.TryGetValue(moduleId, out key)) {
                key = GetModuleName(moduleId);
                if (!string.IsNullOrEmpty(key)) {
                    key = key + "." + moduleId;
                    otherClusterRouteKey.TryAdd(moduleId, key);
                }
            }

            return key;
        }

        //----------------------------=其他模块的路由键-------------------

        private readonly ConcurrentDictionary<int, string> otherEveryOneRouteKey = new ConcurrentDictionary<int, string>();
        /// <summary>
        /// 任意节点路由键
        /// </summary>
        /// <param name="moduleId"></param>
        /// <returns></returns>
        public string GetEveryOneRouteKey(int moduleId) {
            string key = null;
            if (!otherEveryOneRouteKey.TryGetValue(moduleId, out key)) {
                key = GetModuleName(moduleId);
                if (!string.IsNullOrEmpty(key)) {
                    key = key + "." + moduleId + ".everyOne";
                    otherEveryOneRouteKey.TryAdd(moduleId, key);
                }
            }
            return key;
        }

        private readonly ConcurrentDictionary<int, string> otherNodeRouteKey = new ConcurrentDictionary<int, string>();
        /// <summary>
        /// 获取某个节点的路由键
        /// </summary>
        /// <param name="moduleId"></param>
        /// <param name="nodeNum"></param>
        /// <returns></returns>
        public string GetNodeRouteKey(int moduleId, int nodeNum) {
            string key = null;
            int pwd = moduleId * 1000 + nodeNum;

            if (!otherNodeRouteKey.TryGetValue(pwd, out key)) {
                key = GetModuleName(moduleId);
                if (!string.IsNullOrEmpty(key)) {
                    key = key + "." + moduleId + ".one." + nodeNum;
                    otherNodeRouteKey.TryAdd(pwd, key);
                }
            }

            return key;
        }

        /// <summary>
        /// 启动
        /// </summary>
        public void Start(ModuleType type, int nodeNum) {
            this.id = (int)type;
            this.nodeNum = nodeNum;
            this.moduleName = Enum.GetName(type.GetType(), type);
            AddModule(id, moduleName);
        }

        /// <summary>
        /// 注册添加模块
        /// </summary>
        public void AddModule(int moduleId, string moduleName) {
            if (!moduleNames.ContainsKey(moduleId)) {
                moduleNames.TryAdd(moduleId, moduleName);
            }
        }

        /// <summary>
        /// 获取模块名称
        /// </summary>
        /// <param name="moduleId"></param>
        /// <returns></returns>
        public string GetModuleName(int moduleId) {
            string result;
            if (!moduleNames.TryGetValue(moduleId, out result)) {
                result = redisManager.db.HashGet(RedisDictionary.moduleNames, moduleId);
            }
            return result;
        }
    }
}
