/*
 * Copyright (C) 2019, Marc Strapetz <marc.strapetz@syntevo.com>
 * Copyright (C) 2019, Matthias Sohn <matthias.sohn@sap.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.util;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.internal.JGitText;

/**
 * Simple limited size cache based on ConcurrentHashMap purging entries in LRU
 * order when reaching size limit
 *
 * @param <K>
 *            the type of keys maintained by this cache
 * @param <V>
 *            the type of mapped values
 *
 * @since 5.1.9
 */
public class SimpleLruCache<K, V> {

	private static class Entry<K, V> {

		private final K key;

		private final V value;

		// pseudo clock timestamp of the last access to this entry
		private volatile long lastAccessed;

		private long lastAccessedSorting;

		Entry(K key, V value, long lastAccessed) {
			this.key = key;
			this.value = value;
			this.lastAccessed = lastAccessed;
		}

		void copyAccessTime() {
			lastAccessedSorting = lastAccessed;
		}

		@SuppressWarnings("nls")
		@Override
		public String toString() {
			return "Entry [lastAccessed=" + lastAccessed + ", key=" + key
					+ ", value=" + value + "]";
		}
	}

	private Lock lock = new ReentrantLock();

	private Map<K, Entry<K,V>> map = new ConcurrentHashMap<>();

	private volatile int maximumSize;

	private int purgeSize;

	// pseudo clock to implement LRU order of access to entries
	private volatile long time = 0L;

	private static void checkPurgeFactor(float purgeFactor) {
		if (purgeFactor <= 0 || purgeFactor >= 1) {
			throw new IllegalArgumentException(
					MessageFormat.format(JGitText.get().invalidPurgeFactor,
							Float.valueOf(purgeFactor)));
		}
	}

	private static int purgeSize(int maxSize, float purgeFactor) {
		return (int) ((1 - purgeFactor) * maxSize);
	}

	/**
	 * Create a new cache
	 *
	 * @param maxSize
	 *            maximum size of the cache, to reduce need for synchronization
	 *            this is not a hard limit. The real size of the cache could be
	 *            slightly above this maximum if multiple threads put new values
	 *            concurrently
	 * @param purgeFactor
	 *            when the size of the map reaches maxSize the oldest entries
	 *            will be purged to free up some space for new entries,
	 *            {@code purgeFactor} is the fraction of {@code maxSize} to
	 *            purge when this happens
	 */
	public SimpleLruCache(int maxSize, float purgeFactor) {
		checkPurgeFactor(purgeFactor);
		this.maximumSize = maxSize;
		this.purgeSize = purgeSize(maxSize, purgeFactor);
	}

	/**
	 * Returns the value to which the specified key is mapped, or {@code null}
	 * if this map contains no mapping for the key.
	 *
	 * <p>
	 * More formally, if this cache contains a mapping from a key {@code k} to a
	 * value {@code v} such that {@code key.equals(k)}, then this method returns
	 * {@code v}; otherwise it returns {@code null}. (There can be at most one
	 * such mapping.)
	 *
	 * @param key
	 *            the key
	 *
	 * @throws NullPointerException
	 *             if the specified key is null
	 *
	 * @return value mapped for this key, or {@code null} if no value is mapped
	 */
	@SuppressWarnings("NonAtomicVolatileUpdate")
	public V get(Object key) {
		Entry<K, V> entry = map.get(key);
		if (entry != null) {
			entry.lastAccessed = tick();
			return entry.value;
		}
		return null;
	}

	/**
	 * Maps the specified key to the specified value in this cache. Neither the
	 * key nor the value can be null.
	 *
	 * <p>
	 * The value can be retrieved by calling the {@code get} method with a key
	 * that is equal to the original key.
	 *
	 * @param key
	 *            key with which the specified value is to be associated
	 * @param value
	 *            value to be associated with the specified key
	 * @return the previous value associated with {@code key}, or {@code null}
	 *         if there was no mapping for {@code key}
	 * @throws NullPointerException
	 *             if the specified key or value is null
	 */
	@SuppressWarnings("NonAtomicVolatileUpdate")
	public V put(@NonNull K key, @NonNull V value) {
		map.put(key, new Entry<>(key, value, tick()));
		if (map.size() > maximumSize) {
			purge();
		}
		return value;
	}

	@SuppressWarnings("NonAtomicVolatileUpdate")
	private long tick() {
		return ++time;
	}

	/**
	 * Returns the current size of this cache
	 *
	 * @return the number of key-value mappings in this cache
	 */
	public int size() {
		return map.size();
	}

	/**
	 * Reconfigures the cache. If {@code maxSize} is reduced some entries will
	 * be purged.
	 *
	 * @param maxSize
	 *            maximum size of the cache
	 *
	 * @param purgeFactor
	 *            when the size of the map reaches maxSize the oldest entries
	 *            will be purged to free up some space for new entries,
	 *            {@code purgeFactor} is the fraction of {@code maxSize} to
	 *            purge when this happens
	 */
	public void configure(int maxSize, float purgeFactor) {
		lock.lock();
		try {
			checkPurgeFactor(purgeFactor);
			this.maximumSize = maxSize;
			this.purgeSize = purgeSize(maxSize, purgeFactor);
			if (map.size() >= maximumSize) {
				purge();
			}
		} finally {
			lock.unlock();
		}
	}

	private void purge() {
		// don't try to compete if another thread already has the lock
		if (lock.tryLock()) {
			try {
				List<Entry> entriesToPurge = new ArrayList<>(map.values());
				// copy access times to avoid other threads interfere with
				// sorting
				for (Entry e : entriesToPurge) {
					e.copyAccessTime();
				}
				Collections.sort(entriesToPurge,
						Comparator.comparingLong(o -> -o.lastAccessedSorting));
				for (int index = purgeSize; index < entriesToPurge
						.size(); index++) {
					map.remove(entriesToPurge.get(index).key);
				}
			} finally {
				lock.unlock();
			}
		}
	}
}
