package com.hikcreate.utils.redis;

import redis.clients.jedis.JedisCluster;

import java.util.List;
import java.util.Set;

/**
 * @auther: lifuyi
 * @date: 2019/1/31 10:53
 * @description:
 */
public class RedisClient {

    public final static String VIRTUAL_COURSE_PREX = "_lc_vc_";

    private JedisCluster jedisCluster;

    public RedisClient() {
    }

    public RedisClient(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }

    /**
     * 获取单值
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return jedisCall((redis) -> redis.get(key));
    }


    public boolean setList(String key, List<String> deviceIPList){
        return jedisCall((redis)->{
            redis.del(key);
            for(String string:deviceIPList){
                redis.lpush(key,string);
            }
            return true;
        });
    }

    public List<String> getObjectList(String key){
        return jedisCall((redis)->redis.lrange(key, 0, -1));
    }


    /**
     * 设置List缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间，0为不超时
     * @return
     */
    public long setList(String key, List<String> value, int cacheSeconds) {
        return jedisCall((redis) -> {
            long result = 0;
            if(redis.exists(key)){
                redis.del(key);
            }
            String[] strArr = new String[value.size()];
            redis.rpush(key, value.toArray(strArr));
            if (cacheSeconds != 0) {
                redis.expire(key, cacheSeconds);
            }
            return result;
        });
    }


    /**
     * 写入值
     *
     * @param key
     * @param value
     * @return
     */
    public String set(String key, String value) {
        return jedisCall((redis) -> redis.set(key, value));
    }

    /**
     * 自增计数
     *
     * @param key
     * @return
     */
    public Long incr(String key) {
        return jedisCall((redis) -> redis.incr(key));
    }

    /**
     * 自增计数
     *
     * @param key
     * @param value 初始值
     * @return
     */
    public Long incrBy(String key, long value) {
        return jedisCall((redis) -> redis.incrBy(key, value));
    }

    /**
     * 自减计数
     *
     * @param key
     * @return
     */
    public Long decr(String key) {
        return jedisCall((redis) -> redis.decr(key));
    }

    /**
     * 自减计数
     *
     * @param key
     * @param value 初始值
     * @return
     */
    public Long decrBy(String key, long value) {
        return jedisCall((redis) -> redis.decrBy(key, value));
    }

    /**
     * 批量获取值
     *
     * @param keys
     * @return
     */
    public List<String> mget(String... keys) {
        return jedisCall((redis) -> redis.mget(keys));
    }

    /**
     * 存储范围值
     *
     * @param key
     * @param offset
     * @param value
     * @return
     */
    public Long setRange(String key, long offset, String value) {
        return jedisCall((redis) -> redis.setrange(key, offset, value));
    }

    /**
     * 获取指定范围的值
     *
     * @param key
     * @param startOffset
     * @param endOffset
     * @return
     */
    public String getRange(String key, int startOffset, int endOffset) {
        return jedisCall((redis) -> redis.getrange(key, startOffset, endOffset));
    }

    /**
     * 指定过期时间存储值
     *
     * @param key
     * @param keepaliveLong 单位秒
     * @param value
     * @return
     */
    public String setex(String key, int keepaliveLong, String value) {
        return jedisCall((redis) -> redis.setex(key, keepaliveLong, value));
    }

    /**
     * 从左边写入
     *
     * @param key
     * @param value
     * @return
     */
    public Long lpush(String key, String value) {
        return jedisCall((redis) -> redis.lpush(key, value));
    }

    /**
     * 出桡
     *
     * @param key
     * @return
     */
    public String lpop(String key) {
        return jedisCall((redis) -> redis.lpop(key));
    }

    /**
     * 从左边开始获取
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<String> lrange(String key, long start, long end) {
        return jedisCall((redis) -> redis.lrange(key, start, end));
    }

    /**
     * 删出指定的值
     *
     * @param key
     * @param count 删出的个数
     * @param value 指定的值
     * @return
     */
    public Long lrem(String key, long count, String value) {
        return jedisCall((redis) -> redis.lrem(key, count, value));
    }

    /**
     * 返回数据长度
     *
     * @param key
     * @return
     */
    public Long lrem(String key) {
        return jedisCall((redis) -> redis.llen(key));
    }

    /**
     * 删出下标这外的元数
     *
     * @param key
     * @return
     */
    public String ltrim(String key, long start, long end) {
        return jedisCall((redis) -> redis.ltrim(key, start, end));
    }

    /**
     * 获取指定下标的元素
     *
     * @param key
     * @param offSet 下标位置
     * @return
     */
    public String lindex(String key, long offSet) {
        return jedisCall((redis) -> redis.lindex(key, offSet));
    }


    /**
     * set集合新增
     *
     * @param key
     * @param value 值
     * @return
     */
    public Long sadd(String key, String value) {
        return jedisCall((redis) -> redis.sadd(key, value));
    }

    /**
     * 返回sets集合所有值
     *
     * @param key
     * @return
     */
    public Set<String> smembers(String key) {
        return jedisCall((redis) -> redis.smembers(key));
    }

    /**
     * 删出sets集合指定的值
     *
     * @param key
     * @return
     */
    public Long srem(String key, String value) {
        return jedisCall((redis) -> redis.srem(key, value));
    }

    /**
     * 指定的值是否存在sets集合中
     *
     * @param key
     * @return
     */
    public Boolean sismember(String key, String value) {
        return jedisCall((redis) -> redis.sismember(key, value));
    }

    /**
     * sets集合求交集
     *
     * @param keys
     * @return
     */
    public Set<String> sinter(String... keys) {
        return jedisCall((redis) -> redis.sinter(keys));
    }

    /**
     * sets集合求并集
     *
     * @param keys
     * @return
     */
    public Set<String> sunion(String... keys) {
        return jedisCall((redis) -> redis.sunion(keys));
    }

    /**
     * sets集合求差集
     *
     * @param keys
     * @return
     */
    public Set<String> sdiff(String... keys) {
        return jedisCall((redis) -> redis.sdiff(keys));
    }

    /**
     * zset中添加元素
     *
     * @param key
     * @param score 权重
     * @param value
     * @return
     */
    public Long zadd(String key, double score, String value) {
        return jedisCall((redis) -> redis.zadd(key, score, value));
    }

    /**
     * 按照权重值排序
     *
     * @param key
     * @param start (0, 开始)
     * @param end   (-1, 取到最后)
     * @return
     */
    public Set<String> zrange(String key, long start, long end) {
        return jedisCall((redis) -> redis.zrange(key, start, end));
    }

    /**
     * 删出指定的值
     *
     * @param key
     * @param value
     * @return
     */
    public Long zrem(String key, String value) {
        return jedisCall((redis) -> redis.zrem(key, value));
    }

    /**
     * 统计zset集合中的元素中
     *
     * @param key
     * @return
     */
    public Long zcard(String key) {
        return jedisCall((redis) -> redis.zcard(key));
    }

    /**
     * 查看zset集合中value权重
     *
     * @param key
     * @param value
     * @return
     */
    public double zscore(String key, String value) {
        return jedisCall((redis) -> redis.zscore(key, value));
    }

    /**
     * 统计zset集合中权重某个范围内（1.0——5.0），元素的个数
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Long zcount(String key, double min, double max) {
        return jedisCall((redis) -> redis.zcount(key, min, max));
    }

    /**
     * hashs中添加元数
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hset(String key, String field, String value) {
        return jedisCall((redis) -> redis.hset(key, field, value));
    }

    /**
     * hashs中添加整型元数
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hincrBy(String key, String field, long value) {
        return jedisCall((redis) -> redis.hincrBy(key, field, value));
    }

    /**
     * 返回hashs中的所有值
     *
     * @param key
     * @return
     */
    public List<String> hvals(String key) {
        return jedisCall((redis) -> redis.hvals(key));
    }

    /**
     * hashs中删除键值对
     *
     * @param key
     * @return
     */
    public Long hdel(String key, String field) {
        return jedisCall((redis) -> redis.hdel(key, field));
    }

    /*
    根据key进行删除
     */
    public Long del(String key) {
        return jedisCall((redis) -> redis.del(key));
    }

    /**
     * hashs中判断是否存在
     *
     * @param key
     * @param field
     * @return
     */
    public Boolean hexists(String key, String field) {
        return jedisCall((redis) -> redis.hexists(key, field));
    }

    /**
     * hashs中获取对应的值
     *
     * @param key
     * @param field
     * @return
     */
    public String hget(String key, String field) {
        return jedisCall((redis) -> redis.hget(key, field));
    }

    /**
     * hashs中获取多个对应的值
     *
     * @param key
     * @param field
     * @return
     */
    public List<String> hmget(String key, String... field) {
        return jedisCall((redis) -> redis.hmget(key, field));
    }

    /**
     * 获取hashs中所有的key
     *
     * @param key
     * @return
     */
    public Set<String> hkeys(String key) {
        return jedisCall((redis) -> redis.hkeys(key));
    }

    /**
     * 指定key有效期
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(String key, Integer seconds) {
        return jedisCall((redis) -> redis.expire(key, seconds));
    }

    /**
     * 判断指定key是否存在
     * @param key
     * @return
     */
    public boolean exitsKey(String key){
        return jedisCall((redis)->redis.exists(key));
    }

    /**
     * 清除所有数据， 慎用
     */
    public String flushDatabase() {
        return jedisCall((redis) -> redis.flushDB());
    }


    private String buildKey(String bkey) {
        return VIRTUAL_COURSE_PREX + bkey;
    }


    @FunctionalInterface
    interface JedisFunction<R> {
        R call(JedisCluster jedis);
    }

    private <R> R jedisCall(JedisFunction<R> function) {
        if (jedisCluster == null) {
            String hosts = PropertyUtil.getProperty("redis.cluster");
            jedisCluster = RedisUtils.getClusterClient(hosts);
        }
        try {
            return function.call(jedisCluster);
        } finally {
        }
    }

}
