package org.jeecg.ctop.material.service.support;

import org.springframework.stereotype.Service;

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.function.Supplier;

@Service
public class DashboardLocalCacheService {

    private final ConcurrentHashMap<String, CacheValue> cache = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public <T> T get(String key, long ttlMillis, Supplier<T> loader) {
        long now = System.currentTimeMillis();
        CacheValue value = cache.compute(key, (cacheKey, oldValue) -> {
            if (oldValue != null && oldValue.expireAt > now) {
                return oldValue;
            }
            return new CacheValue(loader.get(), now + ttlMillis);
        });
        return value == null ? null : (T) value.value;
    }

    @SuppressWarnings("unchecked")
    public <T> T getIfCacheable(String key, long ttlMillis, Supplier<T> loader, Predicate<T> cacheablePredicate) {
        long now = System.currentTimeMillis();
        CacheValue cachedValue = cache.get(key);
        if (cachedValue != null && cachedValue.expireAt > now) {
            return (T) cachedValue.value;
        }
        T loadedValue = loader.get();
        if (cacheablePredicate == null || cacheablePredicate.test(loadedValue)) {
            cache.put(key, new CacheValue(loadedValue, now + ttlMillis));
        }
        return loadedValue;
    }

    private static class CacheValue {
        private final Object value;
        private final long expireAt;

        private CacheValue(Object value, long expireAt) {
            this.value = value;
            this.expireAt = expireAt;
        }
    }
}
