package org.apache.yoko.util.concurrent;

import org.apache.yoko.util.*;

import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ReferenceCountedCache<K, V> implements Cache<K,V> {

    private final ConcurrentMap<K, CountedEntry<K, V>> map = new ConcurrentHashMap<>();
    private final Fifa<CountedEntry<K, V>> idleEntries = new ConcurrentFifo<>();
    private volatile int threshold;
    private volatile int sweep;
    private final Cleaner<V> cleaner;
    private final ReferenceQueue<Reference<V>> gcQueue;

    /**
     * Create a new cache
     * @param cleaner   the object to use to clean entries
     * @param threshold the number of values above which to start cleaning up
     * @param sweep     the number of unused values to clear up
     */
    public ReferenceCountedCache(Cleaner<V> cleaner, int threshold, int sweep) {
        this.threshold = threshold;
        this.sweep = sweep;
        this.cleaner = cleaner;
        gcQueue = new ReferenceQueue<>();
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public int idleCount() {
        return idleEntries.size();
    }

    @Override
    public Reference<V> get(K key) {
        CountedEntry<K, V> entry = map.get(key);
        if (entry == null) return null;
        return entry == null ? null : track(entry.obtain());
    }

    @Override
    public Reference<V> getOrCreate(K key, KeyedFactory<K, V> valueFactory) {
        CountedEntry<K,V>.ValueReference result;
        do {
            CountedEntry<K, V> entry = map.get(key);
            if (entry == null) {
                // try putting a new entry in the map
                CountedEntry<K, V> newEntry = new CountedEntry<>(key, idleEntries);
                entry = map.putIfAbsent(key, newEntry);
                if (entry == null) {
                    // this thread won the race to create the new entry
                    V value = null;
                    try {
                        value = valueFactory.create(key);
                        return track(newEntry.setValue(value));
                    } finally {
                        if (value == null) {
                            // create() threw an exception, so clean up
                            // and make sure no-one else tries to use this entry
                            newEntry.abort();
                            map.remove(key, newEntry);
                        }
                    }
                }
            }
            result = entry.obtain();
        } while (result == null); // the entry was cleared - try again
        return track(result);
    }

    protected CountedEntry<K,V>.ValueReference track(CountedEntry<K,V>.ValueReference ref) {return ref;}

    @Override
    public final Reference<V> getOrCreate(K key, final Factory<V> factory) {
        return getOrCreate(key, new KeyedFactory<K, V>() {
            @Override
            public V create(K key) {
                return factory.create();
            }
        });
    }

    @Override
    public void remove(Reference<V> ref) {remove(((CountedEntry<K,V>.ValueReference) ref).invalidateAndGetEntry());}

    protected void remove(CountedEntry<K,V> entry) {if (entry != null) map.remove(entry.key, entry);}

    @Override
    public int clean() {
        if (size() <= threshold) return 0;
        int removed = 0;
        while (removed < sweep) {
            CountedEntry<K, V> e = idleEntries.peek();
            if (e == null) break;
            V clearedValue = e.clear();
            if (clearedValue == null) continue;
            if (!!!map.remove(e.key, e))
                throw new IllegalStateException("Entry already removed");
            cleaner.clean(clearedValue);
            removed++;
        }
        return removed;
    }

    @Override
    public Map<K, V> snapshot() {
        Map<K, V> result = new HashMap<>();
        for (Map.Entry<K,CountedEntry<K, V>> entry : map.entrySet()) {
            try (Reference<V> ref = entry.getValue().obtain()){
                result.put(entry.getKey(), ref.get());
            } catch (NullPointerException ignored) {}
        }
        return result;
    }
}
