package xyz.wbsite.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Cache：缓存接口，定义缓存操作。实现有：RedisCache、EhCacheCache、ConcurrentMapCache等
 * CacheManager：缓存管理器，管理各种缓存(Cache)组件
 *
 * @EnableCaching 开启缓存
 * @Cacheable 方法注解，执行方法并缓存结果，有缓存时直接返回缓存不执行方法condition:是否使用缓存 unless:是否缓存结果
 * @CacheEvict： 清空缓存
 * @CachePut： 方法注解，执行方法并缓存结果
 * <p>
 * keyGenerator 缓存数据时key生成策略
 * serialize 缓存数据时value序列化策略
 */
@Configuration
@EnableCaching
@EnableScheduling
public class CacheConfig {

    @Autowired
    private CacheConfig cacheConfig;

    private Map<Object, Long> expireMap = new HashMap<>();

    public static final String DEFAULT_CACHE_NAME = "default_cache_name";

    public <T> T put(Object key, T value) {
        return cacheConfig.put(key, value, 0);
    }

    @Cacheable(value = DEFAULT_CACHE_NAME, key = "#key", unless = "#result==null")
    public <T> T put(Object key, T value, long expire) {
        if (value != null && expire > 0) {
            expireMap.put(key, System.currentTimeMillis() + expire);
        }
        return value;
    }

    @CacheEvict(cacheNames = DEFAULT_CACHE_NAME, key = "#key")
    public void clear(Object key) {

    }

    public Object get(Object key) {
        return cacheConfig.get(key, Object.class);
    }

    public <T> T get(Object key, Class<T> tClass) {
        return cacheConfig.put(key, null);
    }

    public Object remove(Object key) {
        return remove(key, Object.class);
    }

    public <T> T remove(Object key, Class<T> tClass) {
        T t = cacheConfig.get(key, tClass);
        cacheConfig.clear(key);
        return t;
    }

    @Scheduled(fixedDelay = 1000)
    public void expireTask() {
        Iterator<Object> iterator = expireMap.keySet().iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            Long aLong = expireMap.get(next);
            if (aLong == null) {
                cacheConfig.remove(next);
                iterator.remove();
            }
            if (aLong < System.currentTimeMillis()) {
                cacheConfig.remove(next);
                iterator.remove();
            }
        }
    }
}
