package com.ssyf.plugs.cache.cache;

import cn.hutool.core.util.ObjectUtil;
import com.ssyf.plugs.cache.CacheMessage;
import com.ssyf.plugs.cache.helper.CacheHelper;
import com.ssyf.plugs.cache.properties.CacheProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis缓存
 * @author huwei
 * @date 2022/11/29 13:35
 */
@Slf4j
public class RedisCache extends AbstractCache {

    private RedisTemplate<String, Object> redisTemplate;

    public RedisCache(String name, CacheProperties cacheProperties , RedisTemplate<String, Object> redisTemplate) {
        super(name, cacheProperties);
        this.redisTemplate = redisTemplate;
    }

    /**
     * 执行底层查询操作
     * @param key
     * @return
     */
    @Override
    protected Object lookup(Object key) {
        String redisKey = redisKey(key);
        Object value = this.redisTemplate.opsForValue().get(redisKey);
        log.debug("从redis中获取数据：{}",value);
        return CacheHelper.parseValue(value);
    }

    @Override
    public void put(Object key, Object value) {
        if (!super.isAllowNullValues() && ObjectUtil.isEmpty(value)) {
            this.evict(key);
            return;
        }

        long expire =  getExpire(this.getName() ,key);
        String redisKey = redisKey(key);
        if(expire > 0) {
            this.redisTemplate.opsForValue().set(redisKey, CacheHelper.wrapValue(value), expire, TimeUnit.MILLISECONDS);
        }else {
            this.redisTemplate.opsForValue().set(redisKey, CacheHelper.wrapValue(value));
        }
    }

    @Override
    public void evict(Object key) {
        this.redisTemplate.delete(redisKey(key));
        push(new CacheMessage(this.getName() ,key ,this.getUniqueKey()));
    }

    @Override
    public void clear() {
        Set<String> scan = this.redisTemplate.keys(this.getName().concat(":*"));
        this.redisTemplate.delete(scan);
    }

    /**
     * 通知其他缓存删除一级缓存
     * @param message
     */
    private void push(CacheMessage message) {
        this.redisTemplate.convertAndSend(this.cacheProperties.getTopic(), message);
    }

    private String redisKey(Object key){
        return this.getName() + ":" + key.toString();
    }

}
