package com.sa.ibiz.demo.config;

import com.github.benmanes.caffeine.cache.CaffeineSpec;
import com.sa.ibiz.demo.ibizutil.cache.layering.LayeringCacheManager;
import com.sa.ibiz.demo.ibizutil.cache.setting.FirstCacheSetting;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;

/**
 * 缓存配置类
 * 1级缓存为caffeine
 * 2级缓存为redis
 */
@Configuration
@EnableConfigurationProperties(CacheProperties.class)
public class CacheConfig {

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
        return RedisCacheManager.create(connectionFactory);
    }

    @Bean
    public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory){
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        return redisCacheWriter;
    }

    @Autowired
    private RedisCacheWriter redisCacheWriter;
    @Autowired
    private RedisCacheConfiguration configuration;

    @Bean
    @Primary
    public CacheManager cacheManager() {
        LayeringCacheManager layeringCacheManager = new LayeringCacheManager();
        setFirstCacheConfig(layeringCacheManager);//Caffeine缓存设置
        layeringCacheManager.setAllowNullValues(true); //允许存null，防止缓存击穿
        layeringCacheManager.setRedisCacheWriter(redisCacheWriter);
        layeringCacheManager.setRedisConfiguration(configuration);
        return layeringCacheManager;
    }

    @Autowired
    private CacheProperties cacheProperties;
    private void setFirstCacheConfig(LayeringCacheManager layeringCacheManager) {
        String specification = cacheProperties.getCaffeine().getSpec();
        if (StringUtils.hasText(specification)) {
            layeringCacheManager.setCaffeineSpec(CaffeineSpec.parse(specification));
        }
        Map<String, FirstCacheSetting> firstCacheSettings = new HashMap<>();
        layeringCacheManager.setFirstCacheSettings(firstCacheSettings);
    }
}