/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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 com.android.mms.util;

import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * A simple cache with the option of using {@link SoftReference SoftReferences} to play well with
 * the garbage collector and an LRU cache eviction algorithm to limit the number
 * of {@link SoftReference SoftReferences}.
 * <p>
 * The interface of this class is a subset of {@link Map}.
 *
 * from Peter Balwin and books app.
 */
public class SimpleCache<K, V> {

    /**
     * A simple LRU cache to prevent the number of {@link Map.Entry} instances
     * from growing infinitely.
     */
    @SuppressWarnings("serial")
    private class SoftReferenceMap extends LinkedHashMap<K, SoftReference<V>> {

        private final int mMaxCapacity;

        public SoftReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) {
            super(initialCapacity, loadFactor, true);
            mMaxCapacity = maxCapacity;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) {
            return size() > mMaxCapacity;
        }
    }

    @SuppressWarnings("serial")
    private class HardReferenceMap extends LinkedHashMap<K, V> {

        private final int mMaxCapacity;

        public HardReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) {
            super(initialCapacity, loadFactor, true);
            mMaxCapacity = maxCapacity;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > mMaxCapacity;
        }
    }

    private static <V> V unwrap(SoftReference<V> ref) {
        return ref != null ? ref.get() : null;
    }

    private final SoftReferenceMap mSoftReferences;
    private final HardReferenceMap mHardReferences;

    /**
     * Constructor.
     *
     * @param initialCapacity the initial capacity for the cache.
     * @param maxCapacity the maximum capacity for the
     *            cache (this value may be large if soft references are used because
     *            {@link SoftReference SoftReferences} don't consume much memory compared to the
     *            larger data they typically contain).
     * @param loadFactor the initial load balancing factor for the internal
     *            {@link LinkedHashMap}
     */
    public SimpleCache(int initialCapacity, int maxCapacity, float loadFactor,
            boolean useHardReferences) {
        if (useHardReferences) {
            mSoftReferences = null;
            mHardReferences = new HardReferenceMap(initialCapacity, maxCapacity, loadFactor);
        } else {
            mSoftReferences = new SoftReferenceMap(initialCapacity, maxCapacity, loadFactor);
            mHardReferences = null;
        }
    }

    /**
     * See {@link Map#get(Object)}.
     */
    public V get(Object key) {
        return mSoftReferences != null ? unwrap(mSoftReferences.get(key))
                : mHardReferences.get(key);
    }

    /**
     * See {@link Map#put(Object, Object)}.
     */
    public V put(K key, V value) {
        return mSoftReferences != null ?
                unwrap(mSoftReferences.put(key, new SoftReference<V>(value)))
                : mHardReferences.put(key, value);
    }

    /**
     * See {@link Map#clear()}.
     */
    public void clear() {
        if (mSoftReferences != null) {
            mSoftReferences.clear();
        } else {
            mHardReferences.clear();
        }
    }

    /**
     * See {@link Map#remove(Object)}.
     */
    public V remove(K key) {
        if (mSoftReferences != null) {
            return unwrap(mSoftReferences.remove(key));
        } else {
            return mHardReferences.remove(key);
        }
    }

}
