/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.collection.maps;

import java.time.Duration;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Interface representing cache container which creates elements on demand and holds them for a while.
 * Some cache implementations can remove entries based on TTL, other on cache size.
 *
 * What is most important about caches, that they don't store strong references.
 * Despite remove strategy defined by cache, every object can be evicted by garbage collector at any time
 * if it decides to release memory.
 *
 * @param <K> K
 * @param <V> V
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public interface Cache<K,V> {

    /**
     * Creates new cache with default behaviour.
     * Look at {@link CacheMap#getInstance(Function)}.
     *
     * @param <K> K
     * @param <V> V
     * @return cache
     */
    static <K,V> Cache<K,V> getInstance() {
        return CacheMap.getInstance(e -> { throw new UnsupportedOperationException(); });
    }

    /**
     * Creates new cache bounded by size.
     * Look at {@link CacheMap#getInstance(int, Function)}.
     *
     * @param capacity capacity
     * @param <K> K
     * @param <V> V
     * @return cache
     */
    static <K,V> Cache<K,V> getInstance(int capacity) {
        return CacheMap.getInstance(capacity, e -> { throw new UnsupportedOperationException(); });
    }

    /**
     * Creates new cache bounded by TTL.
     * Look at {@link CacheMap#getInstance(Duration, Function)}.
     *
     * @param ttl ttl
     * @param <K> K
     * @param <V> V
     * @return cache
     */
    static <K,V> Cache<K,V> getInstance(Duration ttl) {
        return CacheMap.getInstance(ttl, e -> { throw new UnsupportedOperationException(); });
    }

    /**
     * Returns value for specified key.
     * Computes and stores result if it was not inside cache.
     *
     * @param key key
     * @param function function
     * @return value
     */
    V get(K key, Function<K,V> function);

    /**
     * Returns value for specified key.
     * Computes and stores result if it was not inside cache.
     *
     * @param key key
     * @param function function
     * @return value
     */
    V get(K key, Supplier<V> function);

    /**
     * Removes all entries from cache
     */
    void clear();
}
