// ***************************************************************************************************************************
// * 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.juneau;

import static org.apache.juneau.internal.ClassUtils.*;
import java.util.*;
import java.util.concurrent.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.reflect.*;

/**
 * Stores a cache of {@link Context} instances mapped by the property stores used to create them.
 *
 * <p>
 * The purpose of this class is to reuse instances of bean contexts, serializers, and parsers when they're being
 * re-created with previously-used property stores.
 *
 * <p>
 * Since serializers and parsers are immutable and thread-safe, we reuse them whenever possible.
 */
@SuppressWarnings("unchecked")
public class ContextCache {

	/**
	 * Reusable cache instance.
	 */
	public static final ContextCache INSTANCE = new ContextCache();

	private final static boolean USE_DEEP_MATCHING = Boolean.getBoolean("ContextCache.useDeepMatching");

	private final ConcurrentHashMap<Class<?>,ConcurrentHashMap<Integer,CacheEntry>> contextCache = new ConcurrentHashMap<>();
	private final ConcurrentHashMap<Class<?>,String[]> prefixCache = new ConcurrentHashMap<>();

	// When enabled, this will spit out cache-hit metrics to the console on shutdown.
	private static final boolean TRACK_CACHE_HITS = Boolean.getBoolean("juneau.trackCacheHits");
	static final Map<String,CacheHit> CACHE_HITS = new ConcurrentHashMap<>();
	static {
		if (TRACK_CACHE_HITS) {
			Runtime.getRuntime().addShutdownHook(
				new Thread() {
					@Override
					public void run() {
						int creates=0, cached=0;
						System.out.println("Cache Hits:  [CacheObject] = [numCreated,numCached,cacheHitPercentage]");
						for (Map.Entry<String,CacheHit> e : CACHE_HITS.entrySet()) {
							CacheHit ch = e.getValue();
							System.out.println("["+e.getKey()+"] = ["+ch.creates+","+ch.cached+","+((ch.cached*100)/(ch.creates+ch.cached))+"%]");
							creates += ch.creates;
							cached += ch.cached;
						}
						if (creates + cached > 0)
							System.out.println("[total] = ["+creates+","+cached+","+((cached*100)/(creates+cached))+"%]");
					}
				}
			);
		}
	}

	static void logCache(Class<?> contextClass, boolean wasCached) {
		if (TRACK_CACHE_HITS) {
			synchronized(ContextCache.class) {
				String c = contextClass.getSimpleName();
				CacheHit ch = CACHE_HITS.get(c);
				if (ch == null)
					ch = new CacheHit();
				if (wasCached)
					ch.cached++;
				else
					ch.creates++;
				ch = CACHE_HITS.put(c, ch);
			}
		}
	}

	static class CacheHit {
		public int creates, cached;
	}

	ContextCache() {}

	/**
	 * Creates a new instance of the specified context-based class, or an existing instance if one with the same
	 * property store was already created.
	 *
	 * @param c The instance of the class to create.
	 * @param ps The property store to use to create the class.
	 * @return The
	 */
	public <T extends Context> T create(Class<T> c, PropertyStore ps) {
		String[] prefixes = getPrefixes(c);

		if (prefixes == null)
			return instantiate(c, ps);

		ConcurrentHashMap<Integer,CacheEntry> m = getContextCache(c);

		Integer hashCode = ps.hashCode(prefixes);
		CacheEntry ce = m.get(hashCode);

		if (ce != null && USE_DEEP_MATCHING && ! ce.ps.equals(ps))
			throw new ContextRuntimeException("Property store hashcode mismatch!", new Object[0]);

		logCache(c, ce != null);

		if (ce == null) {
			ce = new CacheEntry(ps, instantiate(c, ps));
			m.putIfAbsent(hashCode, ce);
		}

		return (T)ce.context;
	}

	private <T extends Context> T instantiate(Class<T> c, PropertyStore ps) {
		try {
			return newInstance(c, ps);
		} catch (ContextRuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new ContextRuntimeException(e, "Could not create instance of class ''{0}''", c);
		}
	}

	private ConcurrentHashMap<Integer,CacheEntry> getContextCache(Class<?> c) {
		ConcurrentHashMap<Integer,CacheEntry> m = contextCache.get(c);
		if (m == null) {
			m = new ConcurrentHashMap<>();
			ConcurrentHashMap<Integer,CacheEntry> m2 = contextCache.putIfAbsent(c, m);
			if (m2 != null)
				m = m2;
		}
		return m;
	}

	private String[] getPrefixes(Class<?> c) {
		String[] prefixes = prefixCache.get(c);
		if (prefixes == null) {
			Set<String> ps = new HashSet<>();
			for (ClassInfo c2 : ClassInfo.of(c).getAllParents()) {
				ConfigurableContext cc = c2.getAnnotation(ConfigurableContext.class);
				if (cc != null) {
					if (cc.nocache()) {
						prefixes = new String[0];
						break;
					}
					if (cc.prefixes().length == 0)
						ps.add(c2.getSimpleName());
					else
						ps.addAll(Arrays.asList(cc.prefixes()));
				}
			}
			prefixes = ps.toArray(new String[ps.size()]);
			String[] p2 = prefixCache.putIfAbsent(c, prefixes);
			if (p2 != null)
				prefixes = p2;
		}
		return prefixes.length == 0 ? null : prefixes;
	}

	private <T> T newInstance(Class<T> cc, PropertyStore ps) throws Exception {
		return (T)castOrCreate(Context.class, cc, true, ps);
	}

	private static class CacheEntry {
		final PropertyStore ps;
		final Context context;

		CacheEntry(PropertyStore ps, Context context) {
			this.ps = ps;
			this.context = context;
		}
	}
}
