/*******************************************************************************
 *  Copyright (c) 2007, 2009 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.director;

import java.io.PrintStream;
import java.io.Serializable;
import java.util.*;

/**
 * The purpose of this class is to provide a two-tier map.
 * MapOf(key1 => MapOf(key2 => value)).
 * Even though this class implements Map the behavior of
 * the methods aren't exactly the same as that of a real
 * Map - especially, entrySet(), keySet() etc. works off
 * the outer map while values() returns all the values of
 * all the inner maps.
 */
public class TwoTierMap implements Map, Serializable {

	private static final long serialVersionUID = 362497720873186265L;

	private Map outerMap;
	private int policy;

	public static final int POLICY_NONE = 0, POLICY_BOTH_MAPS_PRESERVE_ORDERING = 1 << 0, POLICY_INNER_MAP_PRESERVE_EXISTING = 1 << 1, POLICY_INNER_MAP_SORTED_ASCENDING = 1 << 2, POLICY_INNER_MAP_SORTED_DESCENDING = 1 << 3, POLICY_INNER_MAP_ENSURE_SINGLETON = 1 << 4;

	private static final int POLICY_INNER_MAP_SORTED_MASK = POLICY_INNER_MAP_SORTED_ASCENDING | POLICY_INNER_MAP_SORTED_DESCENDING;

	public TwoTierMap() {
		this(8, POLICY_NONE);
	}

	public TwoTierMap(int initialCapacity) {
		this(initialCapacity, POLICY_NONE);
	}

	/**
	 * Creates a two-tier map with the specified
	 * initialCapacity and policy. The policy determines
	 * whether the outer map is ordered, inner map is
	 * sorted, clobber values of inner map etc.
	 */
	public TwoTierMap(int initialCapacity, int policy) {
		this.policy = policy;
		this.outerMap = shouldUseOrderedMap() ? new LinkedHashMap(initialCapacity) : new HashMap(initialCapacity);
	}

	/**
	 * Insert the value with key key1 into the inner map 
	 * that is obtained from the outer map with key key2.
	 * If you have set POLICY_INNER_MAP_PRESERVE_EXISTING
	 * at the time of creating this, it will not overwrite
	 * if there is already a non-null value at key2. 
	 * The other POLICY_INNER_MAP_* policies determine 
	 * what kind of inner map is created.
	 * @param key1 The key for outer map.
	 * @param key2 The key for inner map.
	 * @param value The value.
	 * @return Existing value if any, otherwise null.
	 */
	public Object put(Object key1, Object key2, Object value) {
		Map innerMap = (Map) this.outerMap.get(key1);
		if (innerMap == null) {
			if (shouldUseSingletonInnerMap()) {
				this.outerMap.put(key1, Collections.singletonMap(key2, value));
				return null;
			}
			innerMap = createInnerMap();
			this.outerMap.put(key1, innerMap);
		}
		// It is faster to check for already existing entry 
		// this way instead of containsKey() check. Of course,
		// this will prevent us from recognizing a null entry, 
		// which I think shouldn't be a problem.
		Object existing = innerMap.put(key2, value);
		if (existing != null && shouldPreserveExisting()) {
			innerMap.put(key2, existing);
		}
		return existing;
	}

	/**
	 * Get the object stored in the inner map using key2
	 * as key where the inner map is obtained from the 
	 * outer map using key1.
	 * @param key1 The key for outer map.
	 * @param key2 The key for inner map.
	 * @return The object for key2 in inner map for key1 
	 * in the outer map. 
	 */
	public Object get(Object key1, Object key2) {
		if (key1 == null || key2 == null)
			return getAll(key1);
		Map innerMap = (Map) this.outerMap.get(key1);
		Object value = innerMap == null ? null : innerMap.get(key2);
		return value;
	}

	/**
	 * Get all the values in the inner map for key1 in
	 * the outer map.
	 * @param key1 The key for outer map.
	 * @return Collection of values in the inner map.
	 */
	public Collection getAll(Object key1) {
		if (key1 == null)
			// return all
			return values();
		Map innerMap = (Map) this.outerMap.get(key1);
		return innerMap == null ? Collections.EMPTY_LIST : Collections.unmodifiableCollection(innerMap.values());

	}

	public Object remove(Object key1, Object key2) {
		if (key1 == null || key2 == null)
			return removeAll(key1);
		Map innerMap = (Map) this.outerMap.get(key1);
		if (innerMap == null)
			return null;
		if (shouldUseSingletonInnerMap()) {
			Object result = innerMap.get(key2);
			if (result != null) {
				this.outerMap.remove(key1);
			}
			return result;
		}
		Object result = innerMap.remove(key2);
		if (result != null && innerMap.isEmpty()) {
			this.outerMap.remove(key1);
		}
		return result;
	}

	public Collection removeAll(Object key1) {
		if (key1 == null)
			return Collections.EMPTY_LIST;
		Map innerMap = (Map) this.outerMap.remove(key1);
		return innerMap == null ? Collections.EMPTY_LIST : innerMap.values();
	}

	/**
	 * Determine whether there exists a valid object for
	 * key2 in the inner map for key1 in the outer map.
	 * @param key1 The key for outer map.
	 * @param key2 The key for inner map.
	 * @return true if a non-null object exists; otherwise
	 * false.
	 */
	public boolean containsKey(Object key1, Object key2) {
		if (key1 == null)
			return false;
		if (key2 == null)
			return containsKey(key1);
		return get(key1, key2) != null;
	}

	/* (non-Javadoc)
	 * @see java.util.Map#clear()
	 */
	public void clear() {
		this.outerMap.clear();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#containsKey(java.lang.Object)
	 */
	public boolean containsKey(Object key) {
		return this.outerMap.containsKey(key);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#containsValue(java.lang.Object)
	 */
	public boolean containsValue(Object value) {
		for (Iterator it = entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			Map innerMap = (Map) entry.getValue();
			if (innerMap.containsValue(value))
				return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see java.util.Map#size()
	 */
	public int size() {
		return this.outerMap.size();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#isEmpty()
	 */
	public boolean isEmpty() {
		return this.size() == 0;
	}

	/* (non-Javadoc)
	 * @see java.util.Map#entrySet()
	 */
	public Set entrySet() {
		return Collections.unmodifiableSet(this.outerMap.entrySet());
	}

	/* (non-Javadoc)
	 * @see java.util.Map#values()
	 */
	public Collection values() {
		ArrayList result = new ArrayList(size());
		for (Iterator it = this.outerMap.keySet().iterator(); it.hasNext();) {
			Object key = it.next();
			// A null key will cause infinite recursion!
			if (key != null) {
				result.addAll(getAll(key));
			}
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see java.util.Map#get(java.lang.Object)
	 */
	public Object get(Object key) {
		if (key instanceof Object[]) {
			Object[] keys = (Object[]) key;
			return get(keys[0], keys[1]);
		} else
			return getAll(key);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#keySet()
	 */
	public Set keySet() {
		return Collections.unmodifiableSet(this.outerMap.keySet());
	}

	/* (non-Javadoc)
	 * @see java.util.Map#put(java.lang.Object, java.lang.Object)
	 */
	public Object put(Object key, Object value) {
		if (key instanceof Object[]) {
			Object[] keys = (Object[]) key;
			return put(keys[0], keys[1], value);
		}
		throw new IllegalArgumentException("First arg should be an array!"); //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see java.util.Map#putAll(java.util.Map)
	 */
	public void putAll(Map t) {
		throw new UnsupportedOperationException();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#remove(java.lang.Object)
	 */
	public Object remove(Object key) {
		if (key instanceof Object[]) {
			Object[] keys = (Object[]) key;
			return remove(keys[0], keys[1]);
		} else
			return removeAll(key);
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		if (this.outerMap.isEmpty()) {
			sb.append("  (Empty)"); //$NON-NLS-1$
		} else {
			for (Iterator it = this.outerMap.entrySet().iterator(); it.hasNext();) {
				Map.Entry entry = (Map.Entry) it.next();
				sb.append("  ").append(entry.getKey()) //$NON-NLS-1$
						.append(" = ") //$NON-NLS-1$
						.append(entry.getValue()).append('\n');
			}
			sb.setLength(sb.length() - 1);
		}
		return sb.toString();
	}

	public void dump(PrintStream ps) {
		if (ps == null) {
			ps = System.out;
		}
		ps.println(this.toString());
	}

	private Map createInnerMap() {
		Map innerMap;
		if (shouldUseSortedInnerMap()) {
			innerMap = new TreeMap(new ValueComparator(shouldSortInAscendingOrder()));
		} else if (shouldUseOrderedMap()) {
			innerMap = new LinkedHashMap(2);
		} else {
			innerMap = new HashMap(2);
		}
		return innerMap;
	}

	private boolean shouldPreserveExisting() {
		return (this.policy & POLICY_INNER_MAP_PRESERVE_EXISTING) == POLICY_INNER_MAP_PRESERVE_EXISTING;
	}

	private boolean shouldUseOrderedMap() {
		return (this.policy & POLICY_BOTH_MAPS_PRESERVE_ORDERING) == POLICY_BOTH_MAPS_PRESERVE_ORDERING;
	}

	private boolean shouldUseSortedInnerMap() {
		return (this.policy & POLICY_INNER_MAP_SORTED_MASK) != 0;
	}

	private boolean shouldSortInAscendingOrder() {
		return (this.policy & POLICY_INNER_MAP_SORTED_MASK) == POLICY_INNER_MAP_SORTED_ASCENDING;
	}

	private boolean shouldUseSingletonInnerMap() {
		return (this.policy & POLICY_INNER_MAP_ENSURE_SINGLETON) == POLICY_INNER_MAP_ENSURE_SINGLETON;
	}

	private static class ValueComparator implements Comparator, Serializable {
		private static final long serialVersionUID = 362497720873186266L;
		private boolean ascending;

		public ValueComparator(boolean ascending) {
			this.ascending = ascending;
		}

		/* (non-Javadoc)
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		public int compare(Object o1, Object o2) {
			try {
				if (o1 instanceof Comparable) {
					int cmp = ((Comparable) o1).compareTo(o2);
					return this.ascending ? cmp : (0 - cmp);
				}
			} catch (Exception e) {
				// Ignore
			}
			return 1;
		}
	}

}
