/*******************************************************************************
 * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/
package org.eclipse.xtext.xbase.lib;

import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure3;
import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
import org.eclipse.xtext.xbase.lib.internal.UnmodifiableMergingMapView;

import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;


/**
 * This is an extension library for {@link Map maps}.
 * 
 * @author Sebastian Zarnekow - Initial contribution and API
 * @author Stephane Galland - Add operators on map structures.
 */
@GwtCompatible public class MapExtensions {

	/**
	 * Applies the given {@code procedure} for each {@link java.util.Map.Entry key value pair} of the given {@code map}. 
	 * 
	 * @param map
	 *            the map. May not be <code>null</code>.
	 * @param procedure
	 *            the procedure. May not be <code>null</code>.
	 */
	public static <K, V> void forEach(Map<K, V> map, Procedure2<? super K, ? super V> procedure) {
		if (procedure == null)
			throw new NullPointerException("procedure");
		for (Map.Entry<K, V> entry : map.entrySet()) {
			procedure.apply(entry.getKey(), entry.getValue());
		}
	}
	
	/**
	 * Applies the given {@code procedure} for each {@link java.util.Map.Entry key value pair} of the given {@code map}. 
	 * The procedure takes the key, the value and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
	 * is returned for all subsequent pairs. The first pair is at index zero.
	 * 
	 * @param map
	 *            the map. May not be <code>null</code>.
	 * @param procedure
	 *            the procedure. May not be <code>null</code>.
	 */
	public static <K, V> void forEach(Map<K, V> map, Procedure3<? super K, ? super V, ? super Integer> procedure) {
		if (procedure == null)
			throw new NullPointerException("procedure");
		int i = 0;
		for (Map.Entry<K, V> entry : map.entrySet()) {
			procedure.apply(entry.getKey(), entry.getValue(), i);
			if (i != Integer.MAX_VALUE)
				i++;
		}
	}
	
	/**
	 * <p>
	 * Returns a filtered live view on top of the original map. Changes to one affect the other.
	 * </p>
	 * 
	 * <p>
	 * The mapping is done lazily. That is, subsequent access of the values in the map will repeatedly apply the
	 * transformation. Characteristics of the original map, such as iteration order, are left intact. Changes in the
	 * original map are reflected in the result map. The results supports removal if the original map supports removal.
	 * </p>
	 * 
	 * @param original
	 *            the original map. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return a filtered view on top of the original map. Never <code>null</code>.
	 */
	public static <K, V> Map<K, V> filter(Map<K, V> original, final Function2<? super K, ? super V, Boolean> predicate) {
		if (predicate == null)
			throw new NullPointerException("predicate");
		return Maps.filterEntries(original, new Predicate<Map.Entry<K, V>>() {
			@Override
			public boolean apply(Map.Entry<K, V> input) {
				Boolean result = predicate.apply(input.getKey(), input.getValue());
				return result.booleanValue();
			}
		});
	}
	
	/**
	 * Add the given pair into the map.
	 *
	 * <p>
	 * If the pair key already exists in the map, its value is replaced
	 * by the value in the pair, and the old value in the map is returned.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param entry the entry (key, value) to add into the map.
	 * @return the value previously associated to the key, or <code>null</code>
	 *     if the key was not present in the map before the addition.
	 * @since 2.15
	 */
	@Inline(value = "$1.put($2.getKey(), $2.getValue())", statementExpression = true)
	public static <K, V> V operator_add(Map<K, V> map, Pair<? extends K, ? extends V> entry) {
		return map.put(entry.getKey(), entry.getValue());
	}

	/**
	 * Add the given entries of the input map into the output map.
	 *
	 * <p>
	 * If a key in the inputMap already exists in the outputMap, its value is
	 * replaced in the outputMap by the value from the inputMap.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param outputMap the map to update.
	 * @param inputMap the entries to add.
	 * @since 2.15
	 */
	@Inline(value = "$1.putAll($2)", statementExpression = true)
	public static <K, V> void operator_add(Map<K, V> outputMap, Map<? extends K, ? extends V> inputMap) {
		outputMap.putAll(inputMap);
	}

	/**
	 * Add the given pair to a given map for obtaining a new map.
	 *
	 * <p>
	 * The replied map is a view on the given map. It means that any change
	 * in the original map is reflected to the result of this operation.
	 * </p>
	 *
	 * <p>
	 * Even if the key of the right operand exists in the left operand, the value in the right operand is preferred.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param left the map to consider.
	 * @param right the entry (key, value) to add into the map.
	 * @return an immutable map with the content of the map and with the given entry.
	 * @throws IllegalArgumentException - when the right operand key exists in the left operand.
	 * @since 2.15
	 */
	@Pure
	@Inline(value = "$3.union($1, $4.singletonMap($2.getKey(), $2.getValue()))",
			imported = { MapExtensions.class, Collections.class })
	public static <K, V> Map<K, V> operator_plus(Map<K, V> left, final Pair<? extends K, ? extends V> right) {
		return union(left, Collections.singletonMap(right.getKey(), right.getValue()));
	}

	/**
	 * Merge the two maps.
	 *
	 * <p>
	 * The replied map is a view on the given map. It means that any change
	 * in the original map is reflected to the result of this operation.
	 * </p>
	 *
	 * <p>
	 * If a key exists in the left and right operands, the value in the right operand is preferred.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param left the left map.
	 * @param right the right map.
	 * @return a map with the merged contents from the two maps.
	 * @throws IllegalArgumentException - when a right operand key exists in the left operand.
	 * @since 2.15
	 */
	@Pure
	@Inline(value = "$3.union($1, $2)", imported = MapExtensions.class)
	public static <K, V> Map<K, V> operator_plus(Map<K, V> left, Map<? extends K, ? extends V> right) {
		return union(left, right);
	}

	/**
	 * Remove a key from the given map.
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param key the key to remove.
	 * @return the removed value, or <code>null</code> if the key was not
	 *     present in the map.
	 * @since 2.15
	 */
	@Inline(value = "$1.remove($2)", statementExpression = true)
	public static <K, V> V operator_remove(Map<K, V> map, K key) {
		return map.remove(key);
	}

	/**
	 * Remove the given pair into the map.
	 *
	 * <p>
	 * If the given key is inside the map, but is not mapped to the given value, the
	 * map will not be changed.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param entry the entry (key, value) to remove from the map.
	 * @return {@code true} if the pair was removed.
	 * @since 2.15
	 */
	@Inline(value = "$1.remove($2.getKey(), $2.getValue())", statementExpression = true)
	public static <K, V> boolean operator_remove(Map<K, V> map, Pair<? extends K, ? extends V> entry) {
		//TODO use the JRE 1.8 API: map.remove(entry.getKey(), entry.getValue());
		final K key = entry.getKey();
		final V storedValue = map.get(entry.getKey());
	        if (!Objects.equal(storedValue, entry.getValue())
			|| (storedValue == null && !map.containsKey(key))) {
	            return false;
        	}
        	map.remove(key);
	        return true;
	}

	/**
	 * Remove pairs with the given keys from the map.
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param keysToRemove the keys of the pairs to remove.
	 * @since 2.15
	 */
	public static <K, V> void operator_remove(Map<K, V> map, Iterable<? super K> keysToRemove) {
		for (final Object key : keysToRemove) {
			map.remove(key);
		}
	}

	/**
	 * Remove the given pair from a given map for obtaining a new map.
	 *
	 * <p>
	 * If the given key is inside the map, but is not mapped to the given value, the
	 * map will not be changed.
	 * </p>
	 *
	 * <p>
	 * The replied map is a view on the given map. It means that any change
	 * in the original map is reflected to the result of this operation.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param left the map to consider.
	 * @param right the entry (key, value) to remove from the map.
	 * @return an immutable map with the content of the map and with the given entry.
	 * @throws IllegalArgumentException - when the right operand key exists in the left operand.
	 * @since 2.15
	 */
	@Pure
	public static <K, V> Map<K, V> operator_minus(Map<K, V> left, final Pair<? extends K, ? extends V> right) {
		return Maps.filterEntries(left, new Predicate<Entry<K, V>>() {
			@Override
			public boolean apply(Entry<K, V> input) {
				return !Objects.equal(input.getKey(), right.getKey()) || !Objects.equal(input.getValue(), right.getValue());
			}
		});
	}

	/**
	 * Replies the elements of the given map except the pair with the given key.
	 *
	 * <p>
	 * The replied map is a view on the given map. It means that any change
	 * in the original map is reflected to the result of this operation.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param key the key to remove.
	 * @return the map with the content of the map except the key.
	 * @since 2.15
	 */
	@Pure
	public static <K, V> Map<K, V> operator_minus(Map<K, V> map, final K key) {
		return Maps.filterKeys(map, new Predicate<K>() {
			@Override
			public boolean apply(K input) {
				return !Objects.equal(input, key);
			}
		});
	}

	/**
	 * Replies the elements of the left map without the pairs in the right map.
	 * If the pair's values differ from
	 * the value within the map, the map entry is not removed.
	 *
	 * <p>
	 * The difference is an immutable
	 * snapshot of the state of the maps at the time this method is called. It
	 * will never change, even if the maps change at a later time.
	 * </p>
	 *
	 * <p>
	 * Since this method uses {@code HashMap} instances internally, the keys of
	 * the supplied maps must be well-behaved with respect to
	 * {@link Object#equals} and {@link Object#hashCode}.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param left the map to update.
	 * @param right the pairs to remove.
	 * @return the map with the content of the left map except the pairs of the right map.
	 * @since 2.15
	 */
	@Pure
	public static <K, V> Map<K, V> operator_minus(Map<K, V> left, final Map<? extends K, ? extends V> right) {
		return Maps.filterEntries(left, new Predicate<Entry<K, V>>() {
			@Override
			public boolean apply(Entry<K, V> input) {
				final V value = right.get(input.getKey());
				if (value == null) {
					return input.getValue() == null && right.containsKey(input.getKey());
				}
				return !Objects.equal(input.getValue(), value);
			}
		});
	}

	/**
	 * Replies the elements of the given map except the pairs with the given keys.
	 *
	 * <p>
	 * The replied map is a view on the given map. It means that any change
	 * in the original map is reflected to the result of this operation.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param map the map to update.
	 * @param keys the keys of the pairs to remove.
	 * @return the map with the content of the map except the pairs.
	 * @since 2.15
	 */
	@Pure
	public static <K, V> Map<K, V> operator_minus(Map<K, V> map, final Iterable<?> keys) {
		return Maps.filterKeys(map, new Predicate<K>() {
			@Override
			public boolean apply(K input) {
				return !Iterables.contains(keys, input);
			}
		});
	}

	/**
	 * Merge the given maps.
	 *
	 * <p>
	 * The replied map is a view on the given two maps.
	 * If a key exists in the two maps, the replied value is the value of the right operand.
	 * </p>
	 *
	 * <p>
	 * Even if the key of the right operand exists in the left operand, the value in the right operand is preferred.
	 * </p>
	 *
	 * <p>
	 * The replied map is unmodifiable.
	 * </p>
	 *
	 * @param <K> type of the map keys.
	 * @param <V> type of the map values.
	 * @param left the left map.
	 * @param right the right map.
	 * @return a map with the merged contents from the two maps.
	 * @since 2.15
	 */
	@Pure
	@Inline(value = "(new $3<$5, $6>($1, $2))", imported = UnmodifiableMergingMapView.class, constantExpression = true)
	public static <K, V> Map<K, V> union(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {
		return new UnmodifiableMergingMapView<K, V>(left, right);
	}

	/**
	 * <p>Returns a map that performs the given {@code transformation} for each value of {@code original} when requested.</p>
	 * 
	 * <p>The mapping is done lazily. That is, subsequent access of the values in the map will repeatedly apply the
	 * transformation. Characteristics of the original map, such as iteration order, are left intact. Changes in the
	 * original map are reflected in the result map. The results supports removal if the original map supports removal.</p>
	 * 
	 * @param original
	 *            the original map. May not be <code>null</code>.
	 * @param transformation
	 *            the transformation. May not be <code>null</code>.
	 * @return a map with equal keys but transformed values. Never <code>null</code>.
	 * @since 2.4
	 */
	@Pure
	public static <K, V1, V2> Map<K, V2> mapValues(Map<K, V1> original, Function1<? super V1, ? extends V2> transformation) {
		return Maps.transformValues(original, new FunctionDelegate<V1, V2>(transformation));
	}

}
