/*
 * Decompiled with CFR 0.152.
 */
package org.jxmpp.util.cache;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jxmpp.util.cache.Cache;
import org.jxmpp.util.cache.LruCache;

public class ExpirationCache<K, V>
implements Cache<K, V>,
Map<K, V> {
    private final LruCache<K, ExpireElement<V>> cache;
    private long defaultExpirationTime;

    public ExpirationCache(int maxSize, long defaultExpirationTime) {
        this.cache = new LruCache(maxSize);
        this.setDefaultExpirationTime(defaultExpirationTime);
    }

    public void setDefaultExpirationTime(long defaultExpirationTime) {
        if (defaultExpirationTime <= 0L) {
            throw new IllegalArgumentException();
        }
        this.defaultExpirationTime = defaultExpirationTime;
    }

    @Override
    public V put(K key, V value) {
        return this.put(key, value, this.defaultExpirationTime);
    }

    public V put(K key, V value, long expirationTime) {
        ExpireElement<V> eOld = this.cache.put(key, new ExpireElement<V>(value, expirationTime));
        if (eOld == null) {
            return null;
        }
        return eOld.element;
    }

    @Override
    public V get(Object key) {
        ExpireElement<V> v = this.cache.get(key);
        if (v == null) {
            return null;
        }
        if (v.isExpired()) {
            this.remove(key);
            return null;
        }
        return v.element;
    }

    @Override
    public V remove(Object key) {
        ExpireElement<V> e = this.cache.remove(key);
        if (e == null) {
            return null;
        }
        return e.element;
    }

    @Override
    public int getMaxCacheSize() {
        return this.cache.getMaxCacheSize();
    }

    @Override
    public void setMaxCacheSize(int maxCacheSize) {
        this.cache.setMaxCacheSize(maxCacheSize);
    }

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

    @Override
    public boolean isEmpty() {
        return this.cache.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return this.cache.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return this.cache.containsValue(value);
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<K, V> entry : m.entrySet()) {
            this.put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public void clear() {
        this.cache.clear();
    }

    @Override
    public Set<K> keySet() {
        return this.cache.keySet();
    }

    @Override
    public Collection<V> values() {
        HashSet res = new HashSet();
        for (ExpireElement<V> value : this.cache.values()) {
            res.add(value.element);
        }
        return res;
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
        HashSet<Map.Entry<K, V>> res = new HashSet<Map.Entry<K, V>>();
        for (Map.Entry<K, ExpireElement<V>> entry : this.cache.entrySet()) {
            res.add(new EntryImpl(entry.getKey(), entry.getValue().element));
        }
        return res;
    }

    private static class EntryImpl<K, V>
    implements Map.Entry<K, V> {
        private final K key;
        private V value;

        public EntryImpl(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return this.key;
        }

        @Override
        public V getValue() {
            return this.value;
        }

        @Override
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }
    }

    private static class ExpireElement<V> {
        public final V element;
        public final long expirationTimestamp;

        public ExpireElement(V element, long expirationTime) {
            this.element = element;
            this.expirationTimestamp = System.currentTimeMillis() + expirationTime;
        }

        public boolean isExpired() {
            return System.currentTimeMillis() > this.expirationTimestamp;
        }

        public int hashCode() {
            return this.element.hashCode();
        }

        public boolean equals(Object other) {
            if (!(other instanceof ExpireElement)) {
                return false;
            }
            ExpireElement otherElement = (ExpireElement)other;
            return this.element.equals(otherElement.element);
        }
    }
}
