/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.commons.jcs3.jcache;

import static org.apache.commons.jcs3.jcache.Asserts.assertNotNull;
import static org.apache.commons.jcs3.jcache.serialization.Serializations.copy;

import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.Configuration;
import javax.cache.configuration.Factory;
import javax.cache.event.CacheEntryEvent;
import javax.cache.event.EventType;
import javax.cache.expiry.Duration;
import javax.cache.expiry.EternalExpiryPolicy;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CacheWriter;
import javax.cache.integration.CacheWriterException;
import javax.cache.integration.CompletionListener;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.EntryProcessorResult;
import javax.management.ObjectName;

import org.apache.commons.jcs3.engine.CacheElement;
import org.apache.commons.jcs3.engine.ElementAttributes;
import org.apache.commons.jcs3.engine.behavior.ICacheElement;
import org.apache.commons.jcs3.engine.behavior.IElementAttributes;
import org.apache.commons.jcs3.engine.behavior.IElementSerializer;
import org.apache.commons.jcs3.jcache.jmx.JCSCacheMXBean;
import org.apache.commons.jcs3.jcache.jmx.JCSCacheStatisticsMXBean;
import org.apache.commons.jcs3.jcache.jmx.JMXs;
import org.apache.commons.jcs3.jcache.proxy.ExceptionWrapperHandler;
import org.apache.commons.jcs3.jcache.thread.DaemonThreadFactory;
import org.apache.commons.jcs3.utils.serialization.StandardSerializer;

// TODO: configure serializer
public class JCSCache<K, V> implements Cache<K, V>
{
    private final ExpiryAwareCache<K, V> delegate;
    private final JCSCachingManager manager;
    private final JCSConfiguration<K, V> config;
    private final CacheLoader<K, V> loader;
    private final CacheWriter<? super K, ? super V> writer;
    private final ExpiryPolicy expiryPolicy;
    private final ObjectName cacheConfigObjectName;
    private final ObjectName cacheStatsObjectName;
    private final String name;
    private volatile boolean closed;
    private final Map<CacheEntryListenerConfiguration<K, V>, JCSListener<K, V>> listeners = new ConcurrentHashMap<>();
    private final Statistics statistics = new Statistics();
    private final ExecutorService pool;
    private final IElementSerializer serializer; // using json/xml should work as well -> don't force Serializable


    public JCSCache(final ClassLoader classLoader, final JCSCachingManager mgr,
                    final String cacheName, final JCSConfiguration<K, V> configuration,
                    final Properties properties, final ExpiryAwareCache<K, V> cache)
    {
        manager = mgr;

        name = cacheName;

        delegate = cache;
        if (delegate.getElementAttributes() == null)
        {
            delegate.setElementAttributes(new ElementAttributes());
        }
        delegate.getElementAttributes().addElementEventHandler(new EvictionListener(statistics));

        config = configuration;

        final int poolSize = Integer.parseInt(property(properties, cacheName, "pool.size", "3"));
        final DaemonThreadFactory threadFactory = new DaemonThreadFactory("JCS-JCache-" + cacheName + "-");
        pool = poolSize > 0 ? Executors.newFixedThreadPool(poolSize, threadFactory) : Executors.newCachedThreadPool(threadFactory);

        try
        {
            serializer = IElementSerializer.class.cast(classLoader.loadClass(property(properties, "serializer", cacheName, StandardSerializer.class.getName())).newInstance());
        }
        catch (final Exception e)
        {
            throw new IllegalArgumentException(e);
        }

        final Factory<CacheLoader<K, V>> cacheLoaderFactory = configuration.getCacheLoaderFactory();
        if (cacheLoaderFactory == null)
        {
            loader = NoLoader.INSTANCE;
        }
        else
        {
            loader = ExceptionWrapperHandler
                    .newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, CacheLoader.class);
        }

        final Factory<CacheWriter<? super K, ? super V>> cacheWriterFactory = configuration.getCacheWriterFactory();
        if (cacheWriterFactory == null)
        {
            writer = NoWriter.INSTANCE;
        }
        else
        {
            writer = ExceptionWrapperHandler
                    .newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, CacheWriter.class);
        }

        final Factory<ExpiryPolicy> expiryPolicyFactory = configuration.getExpiryPolicyFactory();
        if (expiryPolicyFactory == null)
        {
            expiryPolicy = new EternalExpiryPolicy();
        }
        else
        {
            expiryPolicy = expiryPolicyFactory.create();
        }

        for (final CacheEntryListenerConfiguration<K, V> listener : config.getCacheEntryListenerConfigurations())
        {
            listeners.put(listener, new JCSListener<>(listener));
        }
        delegate.init(this, listeners);

        statistics.setActive(config.isStatisticsEnabled());

        final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", ".");
        final String cacheStr = name.replaceAll(",|:|=|\n", ".");
        try
        {
            cacheConfigObjectName = new ObjectName("javax.cache:type=CacheConfiguration,"
                    + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr);
            cacheStatsObjectName = new ObjectName("javax.cache:type=CacheStatistics,"
                    + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr);
        }
        catch (final Exception e)
        {
            throw new IllegalArgumentException(e);
        }
        if (config.isManagementEnabled())
        {
            JMXs.register(cacheConfigObjectName, new JCSCacheMXBean<>(this));
        }
        if (config.isStatisticsEnabled())
        {
            JMXs.register(cacheStatsObjectName, new JCSCacheStatisticsMXBean(statistics));
        }
    }

    private static String property(final Properties properties, final String cacheName, final String name, final String defaultValue)
    {
        return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue));
    }

    private void assertNotClosed()
    {
        if (isClosed())
        {
            throw new IllegalStateException("cache closed");
        }
    }

    @Override
    public V get(final K key)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        final long getStart = Times.now(false);
        return doGetControllingExpiry(getStart, key, true, false, false, true);
    }

    private V doLoad(final K key, final boolean update, final long now, final boolean propagateLoadException)
    {
        V v = null;
        try
        {
            v = loader.load(key);
        }
        catch (final CacheLoaderException e)
        {
            if (propagateLoadException)
            {
                throw e;
            }
        }
        if (v != null)
        {
            final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation();
            if (isNotZero(duration))
            {
                final IElementAttributes clone = delegate.getElementAttributes().clone();
                if (ElementAttributes.class.isInstance(clone))
                {
                    ElementAttributes.class.cast(clone).setCreateTime();
                }
                final ICacheElement<K, V> element = updateElement(key, v, duration, clone);
                try
                {
                    delegate.update(element);
                }
                catch (final IOException e)
                {
                    throw new CacheException(e);
                }
            }
        }
        return v;
    }

    private ICacheElement<K, V> updateElement(final K key, final V v, final Duration duration, final IElementAttributes attrs)
    {
        final ICacheElement<K, V> element = new CacheElement<>(name, key, v);
        if (duration != null)
        {
            attrs.setTimeFactorForMilliseconds(1);
            final boolean eternal = duration.isEternal();
            attrs.setIsEternal(eternal);
            if (!eternal)
            {
                attrs.setLastAccessTimeNow();
            }
            // MaxLife = -1 to use IdleTime excepted if jcache.ccf asked for something else
        }
        element.setElementAttributes(attrs);
        return element;
    }

    private void touch(final K key, final ICacheElement<K, V> element)
    {
        if (config.isStoreByValue())
        {
            final K copy = copy(serializer, manager.getClassLoader(), key);
            try
            {
                delegate.update(new CacheElement<>(name, copy, element.getVal(), element.getElementAttributes()));
            }
            catch (final IOException e)
            {
                throw new CacheException(e);
            }
        }
    }

    @Override
    public Map<K, V> getAll(final Set<? extends K> keys)
    {
        assertNotClosed();
        for (final K k : keys)
        {
            assertNotNull(k, "key");
        }

        final long now = Times.now(false);
        final Map<K, V> result = new HashMap<>();
        for (final K key : keys) {
            assertNotNull(key, "key");

            final ICacheElement<K, V> elt = delegate.get(key);
            V val = elt != null ? elt.getVal() : null;
            if (val == null && config.isReadThrough())
            {
                val = doLoad(key, false, now, false);
                if (val != null)
                {
                    result.put(key, val);
                }
            }
            else if (elt != null)
            {
                final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
                if (isNotZero(expiryForAccess))
                {
                    touch(key, elt);
                    result.put(key, val);
                }
                else
                {
                    forceExpires(key);
                }
            }
        }
        return result;
    }

    @Override
    public boolean containsKey(final K key)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        return delegate.get(key) != null;
    }

    @Override
    public void put(final K key, final V rawValue)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(rawValue, "value");

        final ICacheElement<K, V> oldElt = delegate.get(key);
        final V old = oldElt != null ? oldElt.getVal() : null;

        final boolean storeByValue = config.isStoreByValue();
        final V value = storeByValue ? copy(serializer, manager.getClassLoader(), rawValue) : rawValue;

        final boolean created = old == null;
        final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate();
        if (isNotZero(duration))
        {
            final boolean statisticsEnabled = config.isStatisticsEnabled();
            final long start = Times.now(false);

            final K jcsKey = storeByValue ? copy(serializer, manager.getClassLoader(), key) : key;
            final ICacheElement<K, V> element = updateElement( // reuse it to create basic structure
                    jcsKey, value, created ? null : duration,
                    oldElt != null ? oldElt.getElementAttributes() : delegate.getElementAttributes().clone());
            if (created && duration != null) { // set maxLife
                final IElementAttributes copy = element.getElementAttributes();
                copy.setTimeFactorForMilliseconds(1);
                final boolean eternal = duration.isEternal();
                copy.setIsEternal(eternal);
                if (ElementAttributes.class.isInstance(copy)) {
                    ElementAttributes.class.cast(copy).setCreateTime();
                }
                if (!eternal)
                {
                    copy.setIsEternal(false);
                    if (duration == expiryPolicy.getExpiryForAccess())
                    {
                        element.getElementAttributes().setIdleTime(duration.getTimeUnit().toMillis(duration.getDurationAmount()));
                    }
                    else
                        {
                        element.getElementAttributes().setMaxLife(duration.getTimeUnit().toMillis(duration.getDurationAmount()));
                    }
                }
                element.setElementAttributes(copy);
            }
            writer.write(new JCSEntry<>(jcsKey, value));
            try
            {
                delegate.update(element);
            }
            catch (final IOException e)
            {
                throw new CacheException(e);
            }
            for (final JCSListener<K, V> listener : listeners.values())
            {
                if (created)
                {
                    listener.onCreated(Arrays.<CacheEntryEvent<? extends K, ? extends V>> asList(new JCSCacheEntryEvent<>(this,
                            EventType.CREATED, null, key, value)));
                }
                else
                {
                    listener.onUpdated(Arrays.<CacheEntryEvent<? extends K, ? extends V>> asList(new JCSCacheEntryEvent<>(this,
                            EventType.UPDATED, old, key, value)));
                }
            }

            if (statisticsEnabled)
            {
                statistics.increasePuts(1);
                statistics.addPutTime(System.currentTimeMillis() - start);
            }
        }
        else
        {
            if (!created)
            {
                forceExpires(key);
            }
        }
    }

    private static boolean isNotZero(final Duration duration)
    {
        return duration == null || !duration.isZero();
    }

    private void forceExpires(final K cacheKey)
    {
        final ICacheElement<K, V> elt = delegate.get(cacheKey);
        delegate.remove(cacheKey);
        for (final JCSListener<K, V> listener : listeners.values())
        {
            listener.onExpired(Arrays.<CacheEntryEvent<? extends K, ? extends V>> asList(new JCSCacheEntryEvent<>(this,
                    EventType.REMOVED, null, cacheKey, elt.getVal())));
        }
    }

    @Override
    public V getAndPut(final K key, final V value)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, true, false);
        put(key, value);
        return v;
    }

    @Override
    public void putAll(final Map<? extends K, ? extends V> map)
    {
        assertNotClosed();
        final TempStateCacheView<K, V> view = new TempStateCacheView<>(this);
        for (final Map.Entry<? extends K, ? extends V> e : map.entrySet())
        {
            view.put(e.getKey(), e.getValue());
        }
        view.merge();
    }

    @Override
    public boolean putIfAbsent(final K key, final V value)
    {
        if (!containsKey(key))
        {
            put(key, value);
            return true;
        }
        return false;
    }

    @Override
    public boolean remove(final K key)
    {
        assertNotClosed();
        assertNotNull(key, "key");

        final boolean statisticsEnabled = config.isStatisticsEnabled();
        final long start = Times.now(!statisticsEnabled);

        writer.delete(key);
        final K cacheKey = key;

        final ICacheElement<K, V> v = delegate.get(cacheKey);
        delegate.remove(cacheKey);

        final V value = v != null && v.getVal() != null ? v.getVal() : null;
        final boolean remove = v != null;
        for (final JCSListener<K, V> listener : listeners.values())
        {
            listener.onRemoved(Arrays.<CacheEntryEvent<? extends K, ? extends V>> asList(new JCSCacheEntryEvent<>(this,
                    EventType.REMOVED, null, key, value)));
        }
        if (remove && statisticsEnabled)
        {
            statistics.increaseRemovals(1);
            statistics.addRemoveTime(Times.now(false) - start);
        }
        return remove;
    }

    @Override
    public boolean remove(final K key, final V oldValue)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(oldValue, "oldValue");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, false, false);
        if (oldValue.equals(v))
        {
            remove(key);
            return true;
        }
        else if (v != null)
        {
            // weird but just for stats to be right (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods())
            expiryPolicy.getExpiryForAccess();
        }
        return false;
    }

    @Override
    public V getAndRemove(final K key)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, true, false);
        remove(key);
        return v;
    }

    private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, final boolean skipLoad,
            final boolean propagateLoadException)
    {
        final boolean statisticsEnabled = config.isStatisticsEnabled();
        final ICacheElement<K, V> elt = delegate.get(key);
        V v = elt != null ? elt.getVal() : null;
        if (v == null && (config.isReadThrough() || forceDoLoad))
        {
            if (!skipLoad)
            {
                v = doLoad(key, false, getStart, propagateLoadException);
            }
        }
        else if (statisticsEnabled)
        {
            if (v != null)
            {
                statistics.increaseHits(1);
            }
            else
            {
                statistics.increaseMisses(1);
            }
        }

        if (updateAcess && elt != null)
        {
            final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
            if (!isNotZero(expiryForAccess))
            {
                forceExpires(key);
            }
            else if (expiryForAccess != null && (!elt.getElementAttributes().getIsEternal() || !expiryForAccess.isEternal()))
            {
                try
                {
                    delegate.update(updateElement(key, elt.getVal(), expiryForAccess, elt.getElementAttributes()));
                }
                catch (final IOException e)
                {
                    throw new CacheException(e);
                }
            }
        }
        if (statisticsEnabled && v != null)
        {
            statistics.addGetTime(Times.now(false) - getStart);
        }
        return v;
    }

    @Override
    public boolean replace(final K key, final V oldValue, final V newValue)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(oldValue, "oldValue");
        assertNotNull(newValue, "newValue");
        final boolean statisticsEnabled = config.isStatisticsEnabled();
        final ICacheElement<K, V> elt = delegate.get(key);
        if (elt != null)
        {
            V value = elt.getVal();
            if (value != null && statisticsEnabled)
            {
                statistics.increaseHits(1);
            }
            if (value == null && config.isReadThrough())
            {
                value = doLoad(key, false, Times.now(false), false);
            }
            if (value != null && value.equals(oldValue))
            {
                put(key, newValue);
                return true;
            }
            else if (value != null)
            {
                final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
                if (expiryForAccess != null && (!elt.getElementAttributes().getIsEternal() || !expiryForAccess.isEternal()))
                {
                    try
                    {
                        delegate.update(updateElement(key, elt.getVal(), expiryForAccess, elt.getElementAttributes()));
                    }
                    catch (final IOException e)
                    {
                        throw new CacheException(e);
                    }
                }
            }
        }
        else if (statisticsEnabled)
        {
            statistics.increaseMisses(1);
        }
        return false;
    }

    @Override
    public boolean replace(final K key, final V value)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");
        final boolean statisticsEnabled = config.isStatisticsEnabled();
        if (containsKey(key))
        {
            if (statisticsEnabled)
            {
                statistics.increaseHits(1);
            }
            put(key, value);
            return true;
        }
        else if (statisticsEnabled)
        {
            statistics.increaseMisses(1);
        }
        return false;
    }

    @Override
    public V getAndReplace(final K key, final V value)
    {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");

        final boolean statisticsEnabled = config.isStatisticsEnabled();

        final ICacheElement<K, V> elt = delegate.get(key);
        if (elt != null)
        {
            V oldValue = elt.getVal();
            if (oldValue == null && config.isReadThrough())
            {
                oldValue = doLoad(key, false, Times.now(false), false);
            }
            else if (statisticsEnabled)
            {
                statistics.increaseHits(1);
            }
            put(key, value);
            return oldValue;
        }
        else if (statisticsEnabled)
        {
            statistics.increaseMisses(1);
        }
        return null;
    }

    @Override
    public void removeAll(final Set<? extends K> keys)
    {
        assertNotClosed();
        assertNotNull(keys, "keys");
        for (final K k : keys)
        {
            remove(k);
        }
    }

    @Override
    public void removeAll()
    {
        assertNotClosed();
        for (final K k : delegate.getKeySet())
        {
            remove(k);
        }
    }

    @Override
    public void clear()
    {
        assertNotClosed();
        try
        {
            delegate.removeAll();
        }
        catch (final IOException e)
        {
            throw new CacheException(e);
        }
    }

    @Override
    public <C2 extends Configuration<K, V>> C2 getConfiguration(final Class<C2> clazz)
    {
        assertNotClosed();
        return clazz.cast(config);
    }

    @Override
    public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
    {
        assertNotClosed();
        assertNotNull(keys, "keys");
        for (final K k : keys)
        {
            assertNotNull(k, "a key");
        }
        pool.submit(() -> doLoadAll(keys, replaceExistingValues, completionListener));
    }

    private void doLoadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
    {
        try
        {
            final long now = Times.now(false);
            for (final K k : keys)
            {
                if (replaceExistingValues)
                {
                    doLoad(k, containsKey(k), now, completionListener != null);
                    continue;
                }
                else if (containsKey(k))
                {
                    continue;
                }
                doGetControllingExpiry(now, k, true, true, false, completionListener != null);
            }
        }
        catch (final RuntimeException e)
        {
            if (completionListener != null)
            {
                completionListener.onException(e);
                return;
            }
        }
        if (completionListener != null)
        {
            completionListener.onCompletion();
        }
    }

    @Override
    public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException
    {
        final TempStateCacheView<K, V> view = new TempStateCacheView<>(this);
        final T t = doInvoke(view, key, entryProcessor, arguments);
        view.merge();
        return t;
    }

    private <T> T doInvoke(final TempStateCacheView<K, V> view, final K key, final EntryProcessor<K, V, T> entryProcessor,
            final Object... arguments)
    {
        assertNotClosed();
        assertNotNull(entryProcessor, "entryProcessor");
        assertNotNull(key, "key");
        try
        {
            if (config.isStatisticsEnabled())
            {
                if (containsKey(key))
                {
                    statistics.increaseHits(1);
                }
                else
                {
                    statistics.increaseMisses(1);
                }
            }
            return entryProcessor.process(new JCSMutableEntry<>(view, key), arguments);
        }
        catch (final Exception ex)
        {
            return throwEntryProcessorException(ex);
        }
    }

    private static <T> T throwEntryProcessorException(final Exception ex)
    {
        if (EntryProcessorException.class.isInstance(ex))
        {
            throw EntryProcessorException.class.cast(ex);
        }
        throw new EntryProcessorException(ex);
    }

    @Override
    public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys, final EntryProcessor<K, V, T> entryProcessor,
            final Object... arguments)
    {
        assertNotClosed();
        assertNotNull(entryProcessor, "entryProcessor");
        final Map<K, EntryProcessorResult<T>> results = new HashMap<>();
        for (final K k : keys)
        {
            try
            {
                final T invoke = invoke(k, entryProcessor, arguments);
                if (invoke != null)
                {
                    results.put(k, () -> invoke);
                }
            }
            catch (final Exception e)
            {
                results.put(k, () -> throwEntryProcessorException(e));
            }
        }
        return results;
    }

    @Override
    public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
    {
        assertNotClosed();
        if (listeners.containsKey(cacheEntryListenerConfiguration))
        {
            throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered");
        }
        listeners.put(cacheEntryListenerConfiguration, new JCSListener<>(cacheEntryListenerConfiguration));
        config.addListener(cacheEntryListenerConfiguration);
    }

    @Override
    public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
    {
        assertNotClosed();
        listeners.remove(cacheEntryListenerConfiguration);
        config.removeListener(cacheEntryListenerConfiguration);
    }

    @Override
    public Iterator<Entry<K, V>> iterator()
    {
        assertNotClosed();
        final Iterator<K> keys = new HashSet<>(delegate.getKeySet()).iterator();
        return new Iterator<Entry<K, V>>()
        {
            private K lastKey;

            @Override
            public boolean hasNext()
            {
                return keys.hasNext();
            }

            @Override
            public Entry<K, V> next()
            {
                lastKey = keys.next();
                return new JCSEntry<>(lastKey, get(lastKey));
            }

            @Override
            public void remove()
            {
                if (isClosed() || lastKey == null)
                {
                    throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()");
                }
                JCSCache.this.remove(lastKey);
            }
        };
    }

    @Override
    public String getName()
    {
        assertNotClosed();
        return name;
    }

    @Override
    public CacheManager getCacheManager()
    {
        assertNotClosed();
        return manager;
    }

    @Override
    public synchronized void close()
    {
        if (isClosed())
        {
            return;
        }

        for (final Runnable task : pool.shutdownNow()) {
            task.run();
        }

        manager.release(getName());
        closed = true;
        close(loader);
        close(writer);
        close(expiryPolicy);
        for (final JCSListener<K, V> listener : listeners.values())
        {
            close(listener);
        }
        listeners.clear();
        JMXs.unregister(cacheConfigObjectName);
        JMXs.unregister(cacheStatsObjectName);
        try
        {
            delegate.removeAll();
        }
        catch (final IOException e)
        {
            throw new CacheException(e);
        }
    }

    private static void close(final Object potentiallyCloseable)
    {
        if (Closeable.class.isInstance(potentiallyCloseable))
        {
            Closeable.class.cast(potentiallyCloseable);
        }
    }

    @Override
    public boolean isClosed()
    {
        return closed;
    }

    @Override
    public <T> T unwrap(final Class<T> clazz)
    {
        assertNotClosed();
        if (clazz.isInstance(this))
        {
            return clazz.cast(this);
        }
        if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class))
        {
            return clazz.cast(delegate);
        }
        throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap");
    }

    public Statistics getStatistics()
    {
        return statistics;
    }

    public void enableManagement()
    {
        config.managementEnabled();
        JMXs.register(cacheConfigObjectName, new JCSCacheMXBean<>(this));
    }

    public void disableManagement()
    {
        config.managementDisabled();
        JMXs.unregister(cacheConfigObjectName);
    }

    public void enableStatistics()
    {
        config.statisticsEnabled();
        statistics.setActive(true);
        JMXs.register(cacheStatsObjectName, new JCSCacheStatisticsMXBean(statistics));
    }

    public void disableStatistics()
    {
        config.statisticsDisabled();
        statistics.setActive(false);
        JMXs.unregister(cacheStatsObjectName);
    }
}
