package com.sckw.redis.utils;

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RedissonUtils {

    private final RedissonClient redissonClient;

    private static RedissonUtils redissonUtils;

    public RedissonUtils(RedissonClient redissonClient) {
        redissonUtils = this;
        this.redissonClient = redissonClient;
    }

    /**
     * 默认缓存时间
     */
    private static final Long DEFAULT_EXPIRED = 5 * 60L;

    /**
     * 添加缓存
     *
     * @param key   key
     * @param value value
     */
    public static void add(String key, String value) {
        //根据key获取bucket桶对象
        RBucket<Object> bucket = redissonUtils.redissonClient.getBucket(key);
        //判读是否存在，并打印日志信息
        if (!bucket.isExists()) {
            //log.info("");
        } else {
            //log.info("update data");
        }
        //添加缓存，若已存在，则替换，设置缓存超时时间
        bucket.set(value, 60, TimeUnit.MINUTES);
    }


    /**
     * 删除缓存信息
     *
     * @param key key
     */
    public static void delete(String key) {
        //根据key获取bucket桶对象
        RBucket<Object> bucket = redissonUtils.redissonClient.getBucket(key);
        //判读是否存在，并打印日志信息
        if (!bucket.isExists()) {
            //log.info("error");
        }
        bucket.delete();
    }

    /**
     * 批量删除
     *
     * @param key 用*模糊匹配
     */
    public static void deleteBactch(String key) {
        Iterator<String> iterator = redissonUtils.redissonClient.getKeys().getKeysByPattern(key).iterator();
        while (iterator.hasNext()) {
            String word = iterator.next();
            RBucket<Object> bucket = redissonUtils.redissonClient.getBucket(word);
            bucket.delete();
        }
    }

    /**
     * 判断缓存是否存在
     *
     * @param key
     * @return
     */
    public static boolean exists(String key) {
        return redissonUtils.redissonClient.getBucket(key).isExists();
    }


    /**
     * 读取缓存
     *
     * @param key 缓存key
     * @param <T>
     * @return 缓存返回值
     */
    public static <T> T get(String key) {
        RBucket<T> bucket = redissonUtils.redissonClient.getBucket(key);
        return bucket.get();
    }

    /**
     * 以string的方式读取缓存
     *
     * @param key 缓存key
     * @return 缓存返回值
     */
    public static String getString(String key) {
        RBucket<String> bucket = redissonUtils.redissonClient.getBucket(key, StringCodec.INSTANCE);
        return bucket.get();
    }

    /**
     * 设置缓存（注：redisson会自动选择序列化反序列化方式）
     *
     * @param key   缓存key
     * @param value 缓存值
     * @param <T>
     */
    public static <T> void put(String key, T value) {
        log.debug("添加缓存【{}】 【{}】开始", key, value);
        RBucket<T> bucket = redissonUtils.redissonClient.getBucket(key);
        bucket.set(value, DEFAULT_EXPIRED, TimeUnit.SECONDS);
    }

    /**
     * 以string的方式设置缓存
     *
     * @param key
     * @param value
     */
    public static void putString(String key, String value, long expired) {
        log.debug("添加缓存【{}】 【{}】开始", key, value);
        RBucket<String> bucket = redissonUtils.redissonClient.getBucket(key, StringCodec.INSTANCE);
        bucket.set(value, expired <= 0 ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);

    }
    /**
     * 以string的方式设置缓存
     *
     * @param key
     * @param value
     */
    public static void putString(String key, String value, long expired, TimeUnit timeUnit) {
        log.debug("添加缓存【{}】 【{}】开始", key, value);
        RBucket<String> bucket = redissonUtils.redissonClient.getBucket(key, StringCodec.INSTANCE);
        bucket.set(value, expired <= 0 ? DEFAULT_EXPIRED : expired, timeUnit);
    }

    /**
     * 如果不存在则写入缓存（string方式，不带有redisson的格式信息）
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expired 缓存过期时间
     */
    public boolean putStringIfAbsent(String key, String value, long expired) {
        log.debug("如果不存在则写入缓存【{}】 【{}】 【{}】开始", key, value, expired);
        RBucket<String> bucket = redissonUtils.redissonClient.getBucket(key, StringCodec.INSTANCE);
        return bucket.setIfAbsent(value, expired <= 0 ? Duration.ofSeconds(DEFAULT_EXPIRED) : Duration.ofSeconds(expired));
    }

    /**
     * 如果不存在则写入缓存（string方式，不带有redisson的格式信息）（不带过期时间，永久保存）
     *
     * @param key   缓存key
     * @param value 缓存值
     */
    public boolean putStringIfAbsent(String key, String value) {
        log.debug("如果不存在则写入永久缓存【{}】 【{}】开始", key, value);
        RBucket<String> bucket = redissonUtils.redissonClient.getBucket(key, StringCodec.INSTANCE);
        return bucket.setIfAbsent(value);
    }

    /**
     * 设置缓存
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expired 缓存过期时间
     * @param <T>     类型
     */
    public static <T> void put(String key, T value, long expired) {
        log.debug("如果不存在则写入缓存【{}】 【{}】 【{}】开始", key, value, expired);
        RBucket<T> bucket = redissonUtils.redissonClient.getBucket(key);
        bucket.set(value, expired <= 0 ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
    }

    /**
     * 移除缓存
     *
     * @param key
     */
    public static void remove(String key) {
        log.debug("移除缓存【{}】开始", key);
        redissonUtils.redissonClient.getBucket(key).delete();
    }

    /**
     * 暴露redisson的RList对象
     *
     * @param key
     * @param <T>
     * @return
     */
    public static <T> RList<T> getRedisList(String key) {
        return redissonUtils.redissonClient.getList(key);
    }

    /**
     * 暴露redisson的RMapCache对象
     *
     * @param key
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> RMapCache<K, V> getRedisMap(String key) {
        return redissonUtils.redissonClient.getMapCache(key);
    }

    /**
     * 暴露redisson的RSET对象
     *
     * @param key
     * @param <T>
     * @return
     */
    public static <T> RSet<T> getRedisSet(String key) {
        return redissonUtils.redissonClient.getSet(key);
    }

    public static <T> boolean putSet(String key, T value) {
        RSet<Object> set = redissonUtils.redissonClient.getSet(key);
        return set.add(value);
    }

    public static <T> boolean putSet(String key, List<T> list) {
        RSet<Object> set = redissonUtils.redissonClient.getSet(key);
        return set.addAll(list);
    }

    public static <T> boolean contains(String key, T value) {
        RSet<Object> set = redissonUtils.redissonClient.getSet(key);
        return set.isEmpty() ? Boolean.FALSE : set.contains(value);
    }

    public static RSet<Object> getSet(String key) {
        return redissonUtils.redissonClient.getSet(key);
    }


    /**
     * 暴露redisson的RScoredSortedSet对象
     *
     * @param key
     * @param <T>
     * @return
     */
    public static <T> RScoredSortedSet<T> getRedisScoredSortedSet(String key) {
        return redissonUtils.redissonClient.getScoredSortedSet(key);
    }

    /**
     * 尝试加锁，最多等待waitTime秒，上锁以后leaseTime秒自动解锁
     *
     * @param lockKey
     * @param waitTime
     * @param leaseTime
     * @return
     */
    public static boolean tryLock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonUtils.redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.info("tryLock lockKey:{} waitTime:{} leaseTime:{}", lockKey, waitTime, leaseTime);
            return false;
        }
    }

    /**
     * @desc: 释放锁
     * @author: yzc
     * @date: 2023-07-13 15:16
     * @Param lockKey:
     * @return: void
     */
    public static void unlock(String lockKey) {
        RLock lock = redissonUtils.redissonClient.getLock(lockKey);
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }

    /**
     * 原子增加
     *
     * @param name
     * @param expired
     * @return
     */
    public static Long getAtomicLong(String name, Long expired) {
        RAtomicLong atomicLong = redissonUtils.redissonClient.getAtomicLong(name);
        long number = atomicLong.incrementAndGet();
        atomicLong.expire(expired <= 0 ? Duration.ofSeconds(DEFAULT_EXPIRED) : Duration.ofSeconds(expired));
        return number;
    }

    /**
     * 原子减少
     *
     * @param name
     * @param expired
     * @return
     */
    public static Long decrementAndGet(String name, Long expired) {
        RAtomicLong atomicLong = redissonUtils.redissonClient.getAtomicLong(name);
        long number = atomicLong.decrementAndGet();
        atomicLong.expire(expired <= 0 ? Duration.ofSeconds(DEFAULT_EXPIRED) : Duration.ofSeconds(expired));
        return number;
    }

    /**
     * 原子set
     *
     * @param name
     * @param value
     * @param expired
     */
    public static void setAtomicLong(String name, Long value, Long expired) {
        RAtomicLong atomicLong = redissonUtils.redissonClient.getAtomicLong(name);
        atomicLong.set(value);
        atomicLong.expire(expired <= 0 ? Duration.ofSeconds(DEFAULT_EXPIRED) : Duration.ofSeconds(expired));
    }


    public static void main(String[] args) {
        List<String> set = new ArrayList<>();
        set.add("asdsad");
        set.add("132146");
        set.add("jgfdt345");
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + "127.0.0.1" + ":" + "6379").setDatabase(1);
        String key = "test:123";
        RedissonClient redissonClient = Redisson.create(config);
        RSet<Object> set1 = redissonClient.getSet(key);
        set1.addAll(set);

        RSet<Object> rSet = redissonClient.getSet(key);
        System.out.println(rSet.contains("jgfdt345"));
    }

}