package br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.cacher;

import br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.model.Cache;
import br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.model.CacheManager;
import br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.model.ValueWrapper;
import br.ufrgs.inf.prosoft.adaptivecaching.cachemanager.util.CacheManagerFactory;
import br.ufrgs.inf.prosoft.adaptivecaching.configuration.types.CacheProviderType;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The type Adaptive method cacher.
 */
public class AdaptiveMethodCacher implements MethodCacher {

    /**
     * The Logger.
     */
    Logger logger = LoggerFactory.getLogger(AdaptiveMethodCacher.class);

    //caching components
    private CacheManager cacheManager;
    private Cache cache;

    /**
     * Instantiates a new Adaptive method cacher.
     *
     * @param cacheProviderType the cache provider type
     * @param expiryInterval    the expiry interval
     */
    public AdaptiveMethodCacher(CacheProviderType cacheProviderType, long expiryInterval) {
        this.cacheManager = CacheManagerFactory.getCacheManager(cacheProviderType, expiryInterval);
        this.cache = cacheManager.getCache("adaptivecaching");
    }

    @Override
    public void putInCache(Object key, Object result) throws Throwable {
        if (result != null) {
            cache.put(key, result);
            logger.debug(key + " with value: " + result + " set in cachemanager");
        }
    }

    @Override
    public Object getFromCache(Object key) throws Throwable {

        ValueWrapper value = cache.get(key);

        if (value != null) {
            logger.debug(key + " with value: " + value.get() + " got from cachemanager");
            return value.get();
        }

        return null;
    }

    @Override
    public void preflush(JoinPoint point) {

    }

    @Override
    public void postflush(JoinPoint point) {

    }

    /**
     * Gets cache.
     *
     * @return the cache
     */
    public Cache getCache() {
        return cache;
    }

    /**
     * Clean cacheable methods expired.
     */
    private void clean() {
        cache.clear();
        logger.info("All cached values were removed.");
    }
}
