using CSRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace QYZH.InteractiveMagazine.Infrastructure.Redis
{
    public static class RedisExtensions
    {
        public static TimeSpan expireSecond = TimeSpan.FromMinutes(20);

        /// <summary>
        /// AddCSRedisCacheExtension
        /// </summary>
        /// <param name="services"></param>
        /// <param name="setupAction"></param>
        /// <returns></returns>
        public static IServiceCollection AddCSRedisCacheExtension(this IServiceCollection services, IConfiguration configuration)
        {
            if (services == null)
                throw new ArgumentNullException("services");

            if (configuration == null)
                throw new ArgumentNullException("configuration");

            var redisOptions = configuration.Get<RedisCacheOption>();
            services.AddSingleton(redisOptions);
            var csredis = new CSRedisClient(redisOptions.ConnectionString, redisOptions.Sentinels, redisOptions.ReadOnly);
            RedisHelper.Initialization(csredis);
            services.AddSingleton(csredis);//csredis注册为单例
            //services.AddSingleton<IDistributedCache>(new Microsoft.Extensions.Caching.Redis.CSRedisCache(RedisHelper.Instance));

            return services;
        }


        /// <summary>
        /// 获取缓存，如果换成不存在则执行方法生成缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <param name="validFor"></param>
        /// <returns></returns>
        public static T GetOrSet<T>(this CSRedisClient redisCache, string key, Func<T> factory, TimeSpan? expireTime = null) where T : class
        {
            var result = redisCache.Get<T>(key);
            if (factory != null && result == null)
            {
                result = factory();
                if (expireTime == null || !expireTime.HasValue)
                    expireTime = expireSecond;

                redisCache.Set(key, result, expireTime.Value);
            }
            return result;
        }

        /// <summary>
        /// 获取缓存，如果缓存不存在则执行方法生成缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <param name="validFor"></param>
        /// <returns></returns>
        public static async Task<T> GetOrSetAsync<T>(this CSRedisClient redisCache, string key, Func<T> factory, TimeSpan? expireTime = null)
        {
            var result = await redisCache.GetAsync<T>(key);
            if (result == null && factory != null)
            {
                result = factory();

                if (expireTime == null || !expireTime.HasValue)
                    expireTime = expireSecond;

                if (result != null)
                    await redisCache.SetAsync(key, result, expireTime.Value);
            }
            return result;
        }
    }



    public class RedisCacheOption
    {
        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// 哨兵设置
        /// </summary>
        public string[] Sentinels { get; set; }

        /// <summary>
        /// 是否只读
        /// </summary>
        public bool ReadOnly { get; set; } = false;

        public int[] ExpireSecondRange { get; set; }

        public int? ExpireSecond { get; set; } = 3600;
    }
}
