using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using CSRedis;
using NHibernate.Cache;

namespace Common
{
    /// <summary>
    /// Redis缓存辅助类
    /// </summary>
    public class CSRedisCacheHelper
    {
        private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(CSRedisCacheHelper));
        public static CSRedisClient redis;
        public static CSRedisClient redis1;
        public static CSRedisClient redis2;
        public static CSRedisClient redis3;
        public static CSRedisClient redis4;
        public static CSRedisClient redis5;
        public static CSRedisClient redis6;
        public static CSRedisClient redis_webchat;
        //private static readonly string[] redisHosts = null;
        private static int SessionExpireMinutes = int.Parse(ConfigurationManager.AppSettings["session_expire_minutes"]);
        private static int MonitorLogExpireMinutes = int.Parse(ConfigurationManager.AppSettings["monitor_log_expire_minutes"]);
        //过期时间60个小时
        private static int DeviceStatusExpireMinutes = 60;
        //private static int RedisMaxReadPool = int.Parse(ConfigurationManager.AppSettings["redis_max_read_pool"]);
        //private static int RedisMaxWritePool = int.Parse(ConfigurationManager.AppSettings["redis_max_write_pool"]);

        //private const string ip = "127.0.0.1";
        //private const string port = "6379";
        //private const string preheat = "100"; // 设置预热连接数
        //private const string connectTimeout = "100"; // 设置连接超时时间
        //private const string tryit = "1"; // 设置重试次数
        //private const string prefix = "CSRedisTest."; // 设置前缀
        //private static readonly string _connectString = $"{ip}:{port},preheat={preheat},connectTimeout={connectTimeout},tryit={tryit},prefix={prefix}";

        public static string HeartBeatPrefix = "HeartBeatMonitor";
        static CSRedisCacheHelper()
        {
            var redisHostStr = ConfigurationManager.AppSettings["redis_server_session"];
            var webchat_redisstr = ConfigurationManager.AppSettings["webchat_redisstr"];
            var webchat_redis_pwd = ConfigurationManager.AppSettings["webchat_redis_pwd"];
            if (!string.IsNullOrEmpty(redisHostStr))
            {
                redis = new CSRedisClient(redisHostStr);//+ ",password=,defaultDatabase=0,poolsize=500,ssl=false,writeBuffer=10240,prefix=");
                //RedisHelper.Initialization(redis);
                //redis = new CSRedisClient[2];
                //redis[0] = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=0");
                //redis[1] = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=1");
                redis1 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=1");
                redis2 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=2");
                redis3 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=3");


                redis4 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=4");
                redis5 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=5");
                redis6 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=6");
                redis_webchat = new CSRedisClient(string.Format(webchat_redisstr + ",password={0},defaultDatabase=0",webchat_redis_pwd));

                //Native subscribe
                string channel = "__keyevent@0__:expired";
                var QQQ = new ValueTuple<string, Action<CSRedisClient.SubscribeMessageEventArgs>>(channel, (msg) =>
                    {
                        //string Key = CacheKey.UPGradeProgressBar + "_" + id;
                        try
                        {
                            if (!msg.Body.StartsWith("UPProgressBar"))
                            {
                                bool containsHyphen = msg.Body.Contains("-");
                                bool isNumeric = msg.Body.All(char.IsDigit);
                                if (containsHyphen == false && isNumeric)
                                {
                                    string hotelcode = Tools.HostNumberToHotelCode(msg.Body).ToString();
                                    OnOffLineData o = new OnOffLineData();
                                    o.HotelCode = hotelcode;
                                    o.HostNumber = msg.Body;
                                    o.CurrentStatus = "off";
                                    o.CurrentTime = DateTime.Now;
                                    //新来的数据
                                    string str = Newtonsoft.Json.JsonConvert.SerializeObject(o);
                                    CSRedisCacheHelper.redis3.Publish("redis-on_off_line", str);

                                    //redis4.Set(HeartBeatPrefix + "_" + msg.Body, 1, 5 * 60);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.Error("RedisYiChu: " + msg.Body);
                            logger.Error(ex.Message);
                        }
                    });
                redis.Subscribe(QQQ);


                //RedisHelper.PSubscribe(new[] { "test*", "*test001", "test*002" }, msg =>
                //{
                //    Console.WriteLine("");
                //});
            }
        }
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void Set<T>(string key, T value)
        {
            redis.Set(key, value, SessionExpireMinutes * 60);
        }

        public static T Get<T>(string key)
        {
            return redis.Get<T>(key);
        }
        public static void Del(string[] key)
        {
            redis.Del(key.ToArray());
        }
        public static void Del_Partition(string key, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.Del(key);
        }

        public static T ForeverGet<T>(string key)
        {
            return redis1.Get<T>(key);
        }

        public static void Forever<T>(string key, T value)
        {
            redis1.Set(key, value, MonitorLogExpireMinutes * 24 * 60 * 60);
        }

        public static T Get_Partition<T>(string key, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            return client.Get<T>(key);
        }
        public static void Set_Partition<T>(string key, T value, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.Set(key, value, DeviceStatusExpireMinutes * 60 * 60);
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="ExpireTime_Minutes"></param>
        /// <param name="SliceNo"></param>
        public static void Set_PartitionWithTime<T>(string key, T value, int ExpireTime_Minutes, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.Set(key, value, ExpireTime_Minutes * 60);
        }
        public static void Set_PartitionWithForever<T>(string key, T value, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.Set(key, value, -1);
        }
        public static void Del_Partition(string[] key, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.Del(key);
        }
        public static bool Contains_Partition(string key, int SliceNo = 2)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            bool result = client.Exists(key);
            return result;
        }
        private static CSRedisClient WhitchRedisSlice(int SliceNo)
        {
            CSRedisClient client = null;
            if (SliceNo == 1)
            {
                client = redis1;
            }
            else if (SliceNo == 2)
            {
                client = redis2;
            }
            else if (SliceNo == 3)
            {
                client = redis3;
            }
            else if (SliceNo == 4)
            {
                client = redis4;
            }
            else if (SliceNo == 5)
            {
                client = redis5;
            }
            else if (SliceNo == 6)
            {
                client = redis6;
            }
            else
            {
                client = redis;
            }
            return client;
        }

        public static long GetForever_ExpireMinutes<T>(string key)
        {
            return redis.Ttl(key);
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T Get<T>(string key, string mac)
        {
            T obj = redis.Get<T>(mac);
            if (obj == null)
            {
                return redis.Get<T>(key);
            }
            return obj;
        }
        /// <summary>
        /// 判断是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <param name="mac"></param>
        /// <returns></returns>
        public static bool Contains(string key, string mac)
        {
            bool result = redis.Exists(mac);
            if (!result)
            {
                result = redis.Exists(key);
            }
            return result;
        }

        public static bool Contains(string key)
        {
            bool result = redis.Exists(key);
            return result;
        }

        public static void Publish(string Topic, string Payload)
        {
            CSRedisCacheHelper.redis3.Publish(Topic, Payload);
        }
        /// <summary>
        /// 添加Hash缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void HMSet(int SliceNo, string key, params object[] value)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.HMSet(key, value);
        }

        public static void HMSet(int SliceNo, int ExpireTime_M, string key, params object[] value)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.HMSet(key, value);
            client.Expire(key, new TimeSpan(0, ExpireTime_M, 0));
        }
        /// <summary>
        /// 获取Hash缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T[] HMGet<T>(int SliceNo, string key, string KeyV)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            return client.HMGet<T>(key, KeyV);
        }
        public static Dictionary<string, string> HMGetAll(int SliceNo, string key)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            return client.HGetAll(key);
        }

        /// <summary>
        /// 获取 某个hash值的数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static int GetHMCount(string key)
        {
            return redis5.HGetAll(key).Count;
        }
        /// <summary>
        /// 删除Hash缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long HDelAll<T>(int SliceNo, string key)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            return client.HDel(key);
        }
        public static long HDel(int SliceNo, string key, string key1)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            return client.HDel(key, key1);
        }

        public static void ListAdd(int SliceNo, string key, params object[] obj)
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);
            client.LPush(key, obj);
        }
        public static int MaxLen = 800000;
        public static void StreamAdd(int SliceNo, string key, string Value)
        {
            try
            {
                CSRedisClient client = WhitchRedisSlice(SliceNo);
                // 添加简单消息
                client.XAdd(key, MaxLen, "*", new ValueTuple<string, string>("__data", Value));
            }
            catch (Exception)
            {

            }
        }
        public static void StreamConsume(int SliceNo, string key, string group = "UDPData", string consumer = "Crics1")
        {
            CSRedisClient client = WhitchRedisSlice(SliceNo);

            var data = redis.XReadGroup(group, consumer, 100, 10, new ValueTuple<string, string>(key, ">"));

            if (data != null)
            {
                //检查pending表的长度
                //消费确认前，pending 应该等于2
                var pending = redis.XPending(key, group);
                foreach (var item in data)
                {
                    var idarray = item.Item2;
                    foreach (var SerializeNo in idarray)
                    {
                        var id1 = SerializeNo.Item1;
                        redis.XAck(key, group, id1);
                        redis.XDel(key, id1);
                    }
                }
            }

        }
    }
}
