/*******************************************************************************
 * Copyright (c) 2009, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.api.tools.internal.model;

import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.internal.core.util.LRUCache;
import org.eclipse.pde.api.tools.internal.SynchronizedOverflowingLRUCache;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;

/**
 * Manages the caches of {@link IApiElement}s
 *
 * @since 1.0.2
 */
public final class ApiModelCache {

	/**
	 * Cache used for {@link IApiElement}s
	 */
	static class Cache<K, V> extends SynchronizedOverflowingLRUCache<K, V> {

		/**
		 * Constructor
		 *
		 * @param size
		 * @param overflow
		 */
		public Cache(int size, int overflow) {
			super(size, overflow);
		}

		@Override
		protected boolean close(LRUCacheEntry<K, V> entry) {
			return true;
		}

		@Override
		protected LRUCache<K, V> newInstance(int size, int newOverflow) {
			return new Cache<>(size, newOverflow);
		}

	}

	static final int DEFAULT_CACHE_SIZE = 1000;
	static final int DEFAULT_OVERFLOW = (int) (DEFAULT_CACHE_SIZE * 0.1f);
	static ApiModelCache fInstance = null;

	Cache<String, Cache<String, Cache<String, IApiElement>>> fRootCache;
	Cache<String, Cache<String, ApiType>> fMemberTypeCache;

	/**
	 * Constructor - no instantiation
	 */
	private ApiModelCache() {
	}

	/**
	 * Returns the singleton instance of this cache
	 *
	 * @return the cache
	 */
	public static synchronized ApiModelCache getCache() {
		if (fInstance == null) {
			fInstance = new ApiModelCache();
		}
		return fInstance;
	}

	/**
	 * Returns the key to use in a cache. The key is of the form:
	 * <code>[baselineid].[componentid].[typename]</code><br>
	 *
	 * @param baseline
	 * @param component
	 * @param typename
	 * @return the member type cache key to use
	 */
	private String getCacheKey(String baseline, String component, String typename) {
		StringBuilder buffer = new StringBuilder();
		buffer.append(baseline).append('.').append(component).append('.').append(typename);
		return buffer.toString();
	}

	/**
	 * Caches the given {@link IApiElement} in the correct cache based on its
	 * type.
	 *
	 * @param element the element to cache
	 * @throws CoreException if there is a problem accessing any of the
	 *             {@link IApiElement} info in order to cache it - pass the
	 *             exception along.
	 */
	public void cacheElementInfo(IApiElement element) throws CoreException {
		switch (element.getType()) {
			case IApiElement.TYPE: {
				if (fRootCache == null) {
					fRootCache = new Cache<>(DEFAULT_CACHE_SIZE / 150, DEFAULT_OVERFLOW / 150);
				}
				IApiComponent comp = element.getApiComponent();
				if (comp != null) {
					IApiBaseline baseline = comp.getBaseline();
					String id = comp.getSymbolicName();
					if (id == null) {
						return;
					}
					Cache<String, Cache<String, IApiElement>> compcache = fRootCache.get(baseline.getName());
					if (compcache == null) {
						compcache = new Cache<>(DEFAULT_CACHE_SIZE / 2, DEFAULT_OVERFLOW / 2);
						fRootCache.put(baseline.getName(), compcache);
					}
					Cache<String, IApiElement> typecache = compcache.get(id);
					if (typecache == null) {
						typecache = new Cache<>(DEFAULT_CACHE_SIZE * 2, DEFAULT_OVERFLOW);
						compcache.put(comp.getSymbolicName(), typecache);
					}
					ApiType type = (ApiType) element;
					if (type.isMemberType() || isMemberType(type.getName()) /*
																			 * cache
																			 * even
																			 * a
																			 * root
																			 * type
																			 * with
																			 * a
																			 * '$'
																			 * in
																			 * its
																			 * name
																			 * here
																			 * as
																			 * well
																			 */) {
						if (this.fMemberTypeCache == null) {
							this.fMemberTypeCache = new Cache<>(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
						}
						String key = getCacheKey(baseline.getName(), id, getRootName(type.getName()));
						Cache<String, ApiType> mcache = this.fMemberTypeCache.get(key);
						if (mcache == null) {
							mcache = new Cache<>(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
							this.fMemberTypeCache.put(key, mcache);
						}
						mcache.put(type.getName(), type);
					} else {
						typecache.put(element.getName(), element);
					}
				}
				break;
			}
			default:
				break;
		}
	}

	/**
	 * Returns the root type name assuming that the '$' char is a member type
	 * boundary
	 *
	 * @param typename
	 * @return the pruned name or the original name
	 */
	private String getRootName(String typename) {
		int idx = typename.indexOf('$');
		if (idx > -1) {
			return typename.substring(0, idx);
		}
		return typename;
	}

	/**
	 * Method to see if the type boundary char appears in the type name
	 *
	 * @param typename
	 * @return true if the type name contains '$' false otherwise
	 */
	private boolean isMemberType(String typename) {
		return typename.indexOf('$') > -1;
	}

	/**
	 * Returns the {@link IApiElement} infos for the element referenced by the
	 * given identifier and of the given type.
	 *
	 * @param baselineid the id of the baseline the component + element belongs
	 *            to
	 * @param componentid the id of the {@link IApiComponent} the element
	 *            resides in
	 * @param identifier for example the qualified name of the type or the id of
	 *            an API component
	 * @param type the kind of the element to look for info for
	 *
	 * @return the cached {@link IApiElement} or <code>null</code> if no such
	 *         element is cached
	 */
	public IApiElement getElementInfo(String baselineid, String componentid, String identifier, int type) {
		String updatedIdentifier = (identifier != null && identifier.startsWith("classes.java.")) ? identifier.substring(8) : identifier; //$NON-NLS-1$
		if (baselineid == null || componentid == null) {
			return null;
		}
		switch (type) {
			case IApiElement.TYPE: {
				if (isMemberType(updatedIdentifier)) {
					if (this.fMemberTypeCache != null) {
						Cache<String, ApiType> mcache = this.fMemberTypeCache.get(getCacheKey(baselineid, componentid, getRootName(updatedIdentifier)));
						if (mcache != null) {
							return mcache.get(updatedIdentifier);
						}
					}
				} else {
					if (this.fRootCache != null) {
						Cache<String, Cache<String, IApiElement>> compcache = fRootCache.get(baselineid);
						if (compcache != null) {
							Cache<String, IApiElement> typecache = compcache.get(componentid);
							if (typecache != null && updatedIdentifier != null) {
								IApiElement ele = typecache.get(updatedIdentifier);
								if (ele != null) {
									return ele;
								}

							}
						}
					}
				}
				break;
			}
			default:
				break;
			}
		if (componentid.startsWith("JavaSE-") && this.fRootCache != null) { //$NON-NLS-1$
			// for system component, retrieve element from any baseline instead
			// of recreating the structure and caching the equivalent element info
			IApiElement element = getElementInfoFromAnyBaseline(baselineid, componentid, updatedIdentifier);
			if (element != null) {
				return element;
			}
		}
		return null;
	}

	private IApiElement getElementInfoFromAnyBaseline(String baselineid, String componentid, String updatedIdentifier) {
		List<String> elements = fRootCache.keysSnapshot();
		for (String otherBaselines : elements) {
				if (otherBaselines.equals(baselineid)) {
					continue;
				}
				Cache<String, Cache<String, IApiElement>> compcache = fRootCache.get(otherBaselines);
				if (compcache != null) {
					Cache<String, IApiElement> typecache = compcache.get(componentid);
					if (typecache != null && updatedIdentifier != null) {
						IApiElement ele = typecache.get(updatedIdentifier);
						if (ele != null) {
							return ele;
						}
					}
				}
			}
		return null;
	}


	/**
	 * Removes the {@link IApiElement} from the given component (given its id)
	 * with the given identifier and of the given type.
	 *
	 * @param componentid the id of the component the element resides in
	 * @param identifier the id (name) of the element to remove
	 * @param type the type of the element (TYPE, METHOD, FIELD, etc)
	 *
	 * @return true if the element was removed, false otherwise
	 */
	public boolean removeElementInfo(String baselineid, String componentid, String identifier, int type) {
		if (baselineid == null) {
			return false;
		}
		switch (type) {
			case IApiElement.TYPE: {
				if (componentid != null && identifier != null) {
					boolean removed = true;
					// clean member type cache
					if (this.fMemberTypeCache != null) {
						if (isMemberType(identifier)) {
							Cache<String, ApiType> mcache = this.fMemberTypeCache.get(getCacheKey(baselineid, componentid, getRootName(identifier)));
							if (mcache != null) {
								return mcache.remove(identifier) != null;
							}
						} else {
							this.fMemberTypeCache.remove(getCacheKey(baselineid, componentid, getRootName(identifier)));
						}
					}
					if (fRootCache != null) {
						Cache<String, Cache<String, IApiElement>> compcache = fRootCache.get(baselineid);
						if (compcache != null) {
							Cache<String, IApiElement> typecache = compcache.get(componentid);
							if (typecache != null) {
								removed &= typecache.remove(identifier) != null;
								if (typecache.isEmpty()) {
									removed &= compcache.remove(componentid) != null;
								}
								if (compcache.isEmpty()) {
									removed &= fRootCache.remove(baselineid) != null;
								}
								return removed;
							}

						}
					} else {
						return false;
					}
				}
				break;
			}
			case IApiElement.COMPONENT: {
				flushMemberCache();
				if (fRootCache != null && componentid != null) {
					Cache<String, Cache<String, IApiElement>> compcache = fRootCache.get(baselineid);
					if (compcache != null) {
						boolean removed = compcache.remove(componentid) != null;
						if (compcache.isEmpty()) {
							removed &= fRootCache.remove(baselineid) != null;
						}
						return removed;
					}
				}
				break;
			}
			case IApiElement.BASELINE: {
				flushMemberCache();
				if (fRootCache != null) {
					return fRootCache.remove(baselineid) != null;
				}
				break;
			}
			default:
				break;
		}
		return false;
	}

	/**
	 * Removes the given {@link IApiElement} info from the cache and returns it
	 * if present
	 *
	 * @param element
	 * @return true if the {@link IApiElement} was removed false otherwise
	 * @throws CoreException if there is a problem accessing any of the
	 *             {@link IApiElement} info in order to remove it from the cache
	 *             - pass the exception along.
	 */
	public boolean removeElementInfo(IApiElement element) {
		if (element == null) {
			return false;
		}
		switch (element.getType()) {
			case IApiElement.COMPONENT:
			case IApiElement.TYPE: {
				if (fRootCache != null) {
					IApiComponent comp = element.getApiComponent();
					if (comp != null) {
						try {
							IApiBaseline baseline = comp.getBaseline();
							return removeElementInfo(baseline.getName(), comp.getSymbolicName(), element.getName(), element.getType());
						} catch (CoreException ce) {
							ApiPlugin.log("Failed to remove element info for " + comp.getName(), ce); //$NON-NLS-1$
						}
					}
				}
				break;
			}
			case IApiElement.BASELINE: {
				flushMemberCache();
				if (fRootCache != null) {
					IApiBaseline baseline = (IApiBaseline) element;
					return fRootCache.remove(baseline.getName()) != null;
				}
				break;
			}
			default:
				break;
		}
		return false;
	}

	/**
	 * Clears out all cached information.
	 */
	public void flushCaches() {
		if (fRootCache != null) {
			fRootCache.flush();
		}
		flushMemberCache();
	}

	/**
	 * Flushes the cache of member types
	 */
	private void flushMemberCache() {
		if (this.fMemberTypeCache != null) {
			this.fMemberTypeCache.flush();
		}
	}

	/**
	 * Returns if the cache has any elements in it or not
	 *
	 * @return true if the cache has no entries, false otherwise
	 */
	public boolean isEmpty() {
		boolean empty = true;
		if (fRootCache != null) {
			empty &= fRootCache.isEmpty();
		}
		if (this.fMemberTypeCache != null) {
			empty &= this.fMemberTypeCache.isEmpty();
		}
		return empty;
	}
}
