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

package net.ranides.assira.reflection.impl;

import java.util.Objects;
import java.util.function.Supplier;

import net.ranides.assira.collection.maps.Cache;
import net.ranides.assira.reflection.IContext;

/**
 * It is helper, context-sensitive cache for key-values.
 * It uses "supplier" to generate non-computed values.
 *
 * @param <T> T
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public class FCache<T> {

    private final Cache<CKey, T> cache = Cache.getInstance();

    /**
     * Returns value assocciated with provied keys.
     * Cache is different for each context.
     *
     * If value does not exist, it will generate it using "supplier".
     *
     * @param context context
     * @param key key
     * @param supplier supplier
     * @return value
     */
    public T get(IContext context, Object key, Supplier<T> supplier) {
        return cache.get(new CKey(context, key), supplier);
    }

    static final class CKey {
        
        private final IContext parent;
        private final Object key;

        public CKey(IContext parent, Object key) {
            this.parent = parent;
            this.key = key;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(this.parent) ^ Objects.hashCode(this.key);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final CKey that = (CKey) obj;
            return (this.parent == that.parent) && Objects.equals(this.key, that.key);
        }

    }
}
