package com.njcn.redis.utils;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author hongawen
 * @version 1.0.0
 * @date 2021年04月30日 09:38
 */
@Component
@RequiredArgsConstructor
public class RedisUtil {

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 指定key的失效时间
     * 秒级别的过期时间
     */
    public void expire(String key, long time) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 根据key获取过期时间
     */
    public long getExpire(String key) {
        Long expireTime = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        return Objects.isNull(expireTime) ? 0 : expireTime;
    }

    /**
     * 判断key是否存在
     */
    public boolean hasKey(String key) {
        Boolean hasKeyFlag = redisTemplate.hasKey(key);
        if (Objects.isNull(hasKeyFlag)) {
            return false;
        }
        return hasKeyFlag;
    }

    /**
     * 删除某个Key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 批量删除keys
     */
    public void deleteKeys(String... keys) {
        redisTemplate.delete(Arrays.asList(keys));
    }


    /**
     * 获取key对应的字符数据
     */
    public String getStringByKey(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取key对应对象数据
     */
    public Object getObjectByKey(String key) {
        return redisTemplate.opsForValue().get(key);
    }


    /**
     * 保存数据
     *
     * @param key   键
     * @param value 值
     */
    public void saveByKey(String key, Object value) {
        redisTemplate.boundValueOps(key).set(value);

    }

    /**
     * 保存数据，指定生命周期（秒）
     *
     * @param key        键
     * @param value      值
     * @param expireTime 生命时间
     */
    public void saveByKeyWithExpire(String key, Object value, Long expireTime) {
        if (expireTime <= 0) {
            saveByKey(key, value);
        } else {
            redisTemplate.boundValueOps(key).set(value, expireTime, TimeUnit.SECONDS);
        }
    }

    /**
     * 顺序的递增和递减
     *
     * @param value 增减根据数值的正负来判断
     */
    public void increment(String key, Long value) {
        redisTemplate.boundValueOps(key).increment(value);
    }


    /**
     * 添加一个Map集合
     */
    public void saveMapValue(String key, Map<String, ?> map, long expireTime) {
        redisTemplate.boundHashOps(key).putAll(map);
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }

    /**
     * 获取map中所有的keys
     */
    public Set<?> getMapKeys(String key) {
        return redisTemplate.boundHashOps(key).keys();
    }

    /**
     * 获取map中所有的values
     */
    public List<?> getMapValues(String key) {
        return redisTemplate.boundHashOps(key).values();
    }

    /**
     * 根据map中某个key获取对应的value
     */
    public Object getMapValueByMapKey(String redisKey, String mapKey) {
        return redisTemplate.boundHashOps(redisKey).get(mapKey);
    }

    /**
     * 根据map中的某个key删除对应的value
     */
    public void deleteMapValueByMapKey(String redisKey, String mapKey) {
        redisTemplate.boundHashOps(redisKey).delete(mapKey);
    }

    /**
     * 判断map中是否有指定的key
     */
    public boolean hasMapKey(String redisKey, String mapKey) {
        Boolean hasKey = redisTemplate.boundHashOps(redisKey).hasKey(mapKey);
        if (Objects.isNull(hasKey)) {
            return false;
        }
        return hasKey;
    }

    /**
     * 右存放List
     */
    public void saveRightListByKey(String key, List<?> values, long expireTime) {
        redisTemplate.boundListOps(key).rightPushAll(values);
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }

    /**
     * 左存放List
     */
    public void saveLeftListByKey(String key, List<?> values, long expireTime) {
        redisTemplate.boundListOps(key).leftPushAll(values);
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }


    /**
     * 获取List某范围的值
     *
     * @param start 起始索引
     * @param end   截止索引
     */
    public List<?> getListRangeValues(String key, long start, long end) {
        long size = getListSize(key);
        if ((start < 0 && end < 0) || (start > end)) {
            start = 0;
            end = size;
        } else if (end > size) {
            end = size;
        } else if (start < 0) {
            start = 0;
        }
        return redisTemplate.boundListOps(key).range(start, end);
    }

    /**
     * 获取List所有数据
     */
    public List<?> getListAllValues(String key) {
        long size = getListSize(key);
        return redisTemplate.boundListOps(key).range(0, size);
    }

    /**
     * 根据指定索引获取指定value
     */
    public Object getListValueByIndex(String key, int index) {
        return redisTemplate.boundListOps(key).index(index);
    }

    /**
     * 获取list长度
     */
    public Long getListSize(String key) {
        return Objects.isNull(redisTemplate.boundListOps(key).size()) ? 0 : redisTemplate.boundListOps(key).size();
    }

    /**
     * 根据索引修改某个值
     */
    public void updateListValueByIndex(String key, int index, Object newObj) {
        redisTemplate.boundListOps(key).set(index, newObj);
    }


}
