/*******************************************************************************
 * Copyright (c) 2011, 2020 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.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;

import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.eclipse.xtext.xbase.lib.internal.BooleanFunctionDelegate;
import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
import org.eclipse.xtext.xbase.lib.internal.KeyComparator;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;

/**
 * This is an extension library for {@link Iterator iterators}.
 * 
 * @author Sven Efftinge - Initial contribution and API
 * @author Sebastian Zarnekow
 */
@GwtCompatible public class IteratorExtensions {

	/**
	 * Wraps an {@link Iterator} in an {@link Iterable}. WARNING: The resulting
	 * {@link Iterable} may be used (e.g. calling
	 * {@link IterableExtensions#isEmpty(Iterable)}) / iterated (e.g. in a for
	 * loop) only once. If you want to create a reusable {@link Iterable} call
	 * {@link IterableExtensions#toList(Iterable)} or
	 * {@link IterableExtensions#toSet(Iterable)} on the result and reuse the
	 * resulting {@link List} / {@link Set}
	 * @param iterator the {@link Iterator} to wrap in an {@link Iterable}. May not be <code>null</code>.
	 * @return an {@link Iterable} providing the given {@link Iterator}. Never <code>null</code>.
	 */
	@Pure
	public static <T> Iterable<T> toIterable(final Iterator<T> iterator) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		return new Iterable<T>() {
			@Override
			public Iterator<T> iterator() {
				return iterator;
			}
		};
	}
	
	/**
	 * <p>
	 * Concatenates two iterators into a single iterator. The returned iterator traverses the
	 * elements in {@code a}, followed by the elements in {@code b}. The resulting iterator is effectivly a view on the
	 * source iterators. That is, the source iterators are not polled until necessary and the result will reflect
	 * changes in the sources.
	 * </p>
	 * <p>
	 * The returned iterator supports {@code remove()} when the corresponding input iterator supports it.
	 * </p>
	 * 
	 * @param a
	 *            the first iterator. May not be <code>null</code>.
	 * @param b
	 *            the second iterator. May not be <code>null</code>.
	 * @return a combined iterator. Never <code>null</code>.
	 */
	@Pure
	@Inline(value="$3.$4concat($1, $2)", imported=Iterators.class)
	public static <T> Iterator<T> operator_plus(Iterator<? extends T> a, Iterator<? extends T> b) {
		return Iterators.concat(a, b);
	}

	/**
	 * Finds the first element in the given iterator that fulfills the predicate. If none is found or the iterator is
	 * empty, <code>null</code> is returned.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return the first element in the iterator for which the given predicate returns <code>true</code>, returns
	 *         <code>null</code> if no element matches the predicate or the iterator is empty.
	 */
	public static <T> T findFirst(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
		if (predicate == null)
			throw new NullPointerException("predicate");
		while(iterator.hasNext()) {
			T t = iterator.next();
			if (predicate.apply(t))
				return t;
		}
		return null;
	}

	/**
	 * Finds the last element in the given iterator that fulfills the predicate. If none is found or the iterator is
	 * empty, <code>null</code> is returned.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return the last element in the iterator for which the given predicate returns <code>true</code>, returns
	 *         <code>null</code> if no element matches the predicate or the iterator is empty.
	 */
	public static <T> T findLast(Iterator<T> iterator, Functions.Function1<? super T, Boolean> predicate) {
		if (predicate == null)
			throw new NullPointerException("predicate");
		T result = null;
		while(iterator.hasNext()) {
			T t = iterator.next();
			if (predicate.apply(t))
				result = t;
		}
		return result;
	}

	/**
	 * Returns the first element in the given iterator or <code>null</code> if empty.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return the first element in the iterator or <code>null</code>.
	 */
	public static <T> T head(Iterator<T> iterator) {
		if (iterator.hasNext())
			return iterator.next();
		return null;
	}

	/**
	 * Returns a view on this iterator that contains all the elements except the first.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return an iterator with all elements except the first. Never <code>null</code>.
	 * @see #drop(Iterator, int)
	 */
	public static <T> Iterator<T> tail(final Iterator<T> iterator) {
		return drop(iterator, 1);
	}

	/**
	 * Returns the last element in the given iterator or <code>null</code> if empty.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return the last element in the iterator or <code>null</code>.
	 */
	public static <T> T last(Iterator<T> iterator) {
		T result = null;
		while(iterator.hasNext()) {
			result = iterator.next();
		}
		return result;
	}

	/**
	 * Returns a view on this iterator that provides at most the first <code>count</code> entries.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param count
	 *            the number of elements that should be returned at most.
	 * @return an iterator with <code>count</code> elements. Never <code>null</code>.
	 * @throws IllegalArgumentException
	 *             if <code>count</code> is negative.
	 */
	@Pure
	public static <T> Iterator<T> take(final Iterator<T> iterator, final int count) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		if (count < 0)
			throw new IllegalArgumentException("Cannot take a negative number of elements. Argument 'count' was: "
					+ count);
		if (count == 0)
			return ImmutableSet.<T>of().iterator();
		return new AbstractIterator<T>() {

			private int remaining = count;

			@Override
			protected T computeNext() {
				if (remaining <= 0)
					return endOfData();
				if (!iterator.hasNext())
					return endOfData();
				remaining--;
				return iterator.next();
			}
		};
	}

	/**
	 * Returns a view on this iterator that provides all elements except the first <code>count</code> entries.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param count
	 *            the number of elements that should be dropped.
	 * @return an iterator without the first <code>count</code> elements. Never <code>null</code>.
	 * @throws IllegalArgumentException
	 *             if <code>count</code> is negative.
	 */
	public static <T> Iterator<T> drop(final Iterator<T> iterator, final int count) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		if (count == 0)
			return iterator;
		if (count < 0)
			throw new IllegalArgumentException("Cannot drop a negative number of elements. Argument 'count' was: "
					+ count);
		return new AbstractIterator<T>() {
			{
				int i = count;
				while (i > 0 && iterator.hasNext()) {
					iterator.next();
					i--;
				}
			}

			@Override
			protected T computeNext() {
				if (!iterator.hasNext())
					return endOfData();
				return iterator.next();
			}
		};
	}

	/**
	 * Returns {@code true} if one or more elements in {@code iterator} satisfy the predicate.
	 * 
     * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return <code>true</code> if one or more elements in {@code iterator} satisfy the predicate.
	 */
	public static <T> boolean exists(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
		if (predicate == null)
			throw new NullPointerException("predicate");
		while(iterator.hasNext()) {
			if (predicate.apply(iterator.next()))
				return true;
		}
		return false;
	}

	/**
	 * Returns {@code true} if every element in {@code iterator} satisfies the predicate. If {@code iterator} is empty,
	 * {@code true} is returned. In other words, <code>false</code> is returned if at least one element fails to fulfill
	 * the predicate.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return <code>true</code> if every element in {@code iterator} satisfies the predicate and also if there is no element.
	 */
	public static <T> boolean forall(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
		if (predicate == null)
			throw new NullPointerException("predicate");
		while(iterator.hasNext()) {
			if (!predicate.apply(iterator.next()))
				return false;
		}
		return true;
	}

	/**
	 * Returns the elements of {@code unfiltered} that satisfy a predicate. The resulting iterator does not
	 * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered
	 * original are reflected in the view.
	 * 
	 * @param unfiltered
	 *            the unfiltered iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return an iterator that contains only the elements that fulfill the predicate. Never <code>null</code>.
	 */
	@Pure
	public static <T> Iterator<T> filter(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) {
		return Iterators.filter(unfiltered, new BooleanFunctionDelegate<T>(predicate));
	}

	/**
	 * Returns the elements of {@code unfiltered} that do not satisfy a predicate. The resulting iterator does not
	 * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered
	 * original are reflected in the view.
	 *
	 * @param unfiltered
	 *            the unfiltered iterator. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate. May not be <code>null</code>.
	 * @return an iterator that contains only the elements that do not fulfill the predicate. Never <code>null</code>.
	 */
	@Pure
	public static <T> Iterator<T> reject(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) {
		return Iterators.filter(unfiltered, Predicates.not(new BooleanFunctionDelegate<T>(predicate)));
	}

	/**
	 * Returns all instances of class {@code type} in {@code unfiltered}. The returned iterator has elements whose class
	 * is {@code type} or a subclass of {@code type}. The returned iterator does not support {@code remove()}.
	 * The returned iterator is a view on the original elements. Changes in the unfiltered original are reflected in
	 * the view.
	 * 
	 * @param unfiltered
	 *            the unfiltered iterator. May not be <code>null</code>.
	 * @param type
	 *            the type of elements desired
	 * @return an unmodifiable iterator containing all elements of the original iterator that were of the requested
	 *         type. Never <code>null</code>.
	 */
	@Pure
	@GwtIncompatible("Class.isInstance")
	@Inline(value="$3.$4filter($1, $2)", imported=Iterators.class)
	public static <T> Iterator<T> filter(Iterator<?> unfiltered, Class<T> type) {
		return Iterators.filter(unfiltered, type);
	}
	
	/**
	 * Returns a new iterator filtering any null references.
	 * 
	 * @param unfiltered
	 *            the unfiltered iterator. May not be <code>null</code>.
	 * @return an unmodifiable iterator containing all elements of the original iterator without any <code>null</code>
	 *         references. Never <code>null</code>.
	 */
	@Pure
	public static <T> Iterator<T> filterNull(Iterator<T> unfiltered) {
		return Iterators.filter(unfiltered, Predicates.notNull());
	}

	/**
	 * Returns an iterator that performs the given {@code transformation} for each element of {@code original} when
	 * requested. The mapping is done lazily. 
	 * 
	 * The returned iterator's iterator supports {@code remove()} if the provided iterator does. After a successful
	 * {@code remove()} call, {@code original} no longer contains the corresponding element.
	 * 
	 * @param original
	 *            the original iterator. May not be <code>null</code>.
	 * @param transformation
	 *            the transformation. May not be <code>null</code>.
	 * @return an iterator that provides the result of the transformation. Never <code>null</code>.
	 */
	@Pure
	public static <T, R> Iterator<R> map(Iterator<T> original, Function1<? super T, ? extends R> transformation) {
		return Iterators.transform(original, new FunctionDelegate<T, R>(transformation));
	}

	/**
	 * Returns an iterable that performs the given {@code transformation} for each element of {@code original} when
	 * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the iterable will
	 * repeatedly apply the transformation.
	 * <p>
	 * The transformation maps each element to an iterable, and all resulting iterables are combined to a single iterable.
	 * Effectively a combination of {@link #map(Iterator, Functions.Function1)} and {@link #flatten(Iterator)} is performed.
	 * </p>
	 * <p>
	 * The returned iterable's iterator <i>does not support {@code remove()}</i> in contrast to {@link #map(Iterator, Functions.Function1)}.
	 * </p>
	 * 
	 * @param original
	 *            the original iterable. May not be <code>null</code>.
	 * @param transformation
	 *            the transformation. May not be <code>null</code> and must not yield <code>null</code>.
	 * @return an iterable that provides the result of the transformation. Never <code>null</code>.
	 * 
	 * @since 2.13
	 */
	@Pure
	public static <T, R> Iterator<R> flatMap(Iterator<T> original, Function1<? super T, ? extends Iterator<R>> transformation) {
		return flatten(map(original, transformation));
	}


	/**
	 * Combines multiple iterators into a single iterator. The returned iterator traverses the
	 * elements of each iterator in {@code inputs}. The input iterators are not polled until necessary.
	 * 
	 * @param inputs
	 *            the to be flattened iterators. May not be <code>null</code>.
	 * @return an iterator that provides the concatenated values of the input elements. Never <code>null</code>.
	 * 
	 * @since 2.13
	 */
	@Inline(value="$2.$3concat($1)", imported=Iterators.class)
	public static <T> Iterator<T> flatten(Iterator<? extends Iterator<? extends T>> inputs) {
		return Iterators.concat(inputs);
	}

	/**
	 * Applies {@code procedure} for each element of the given iterator.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param procedure
	 *            the procedure. May not be <code>null</code>.
	 */
	public static <T> void forEach(Iterator<T> iterator, Procedure1<? super T> procedure) {
		if (procedure == null)
			throw new NullPointerException("procedure");
		while(iterator.hasNext()) {
			procedure.apply(iterator.next());
		}
	}
	
	/**
	 * Applies {@code procedure} for each element of the given iterator.
	 * The procedure takes the element and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
	 * is returned for all subsequent elements. The first element is at index zero.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param procedure
	 *            the procedure. May not be <code>null</code>.
	 */
	public static <T> void forEach(Iterator<T> iterator, Procedure2<? super T, ? super Integer> procedure) {
		if (procedure == null)
			throw new NullPointerException("procedure");
		int i = 0;
		while(iterator.hasNext()) {
			procedure.apply(iterator.next(), i);
			if (i != Integer.MAX_VALUE)
				i++;
		}
	}

	/**
	 * Returns the concatenated string representation of the elements in the given iterator. No delimiter is used.
	 * The given iterator is left exhausted.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return the string representation of the iterator's elements. Never <code>null</code>.
	 * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
	 */
	public static String join(Iterator<?> iterator) {
		return join(iterator, "");
	}

	/**
	 * Returns the concatenated string representation of the elements in the given iterator. The {@code separator} is
	 * used to between each pair of entries in the input. The string <code>null</code> is used for <code>null</code>
	 * entries in the input. The given iterator is left exhausted.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param separator
	 *            the separator. May not be <code>null</code>.
	 * @return the string representation of the iterator's elements. Never <code>null</code>.
	 * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
	 */
	public static String join(Iterator<?> iterator, CharSequence separator) {
		return Joiner.on(separator.toString()).useForNull("null").join(toIterable(iterator));
	}

	/**
	 * Returns the concatenated string representation of the elements in the given iterator. The {@code function} is
	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
	 * for an entry. The given iterator is left exhausted.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param separator
	 *            the separator. May not be <code>null</code>.
	 * @param function
	 *            the function that is used to compute the string representation of a single element. May not be
	 *            <code>null</code>.
	 * @return the string representation of the iterator's elements. Never <code>null</code>.
	 */
	public static <T> String join(Iterator<T> iterator, CharSequence separator,
			Functions.Function1<? super T, ? extends CharSequence> function) {
		if (separator == null)
			throw new NullPointerException("separator");
		if (function == null)
			throw new NullPointerException("function");
		StringBuilder result = new StringBuilder();
		while (iterator.hasNext()) {
			T next = iterator.next();
			CharSequence elementToString = function.apply(next);
			result.append(elementToString);
			if (iterator.hasNext())
				result.append(separator);
		}
		return result.toString();
	}
	
	/**
	 * Returns the concatenated string representation of the elements in the given iterator. The {@code function} is
	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
	 * for an entry. The given iterator is left exhausted.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @param before
	 *            prepends the resulting string if the iterator contains at least one element. May be <code>null</code> which is equivalent to passing an empty string.
	 * @param separator
	 *            the separator. May be <code>null</code> which is equivalent to passing an empty string.
	 * @param after
	 *            appended to the resulting string if the iterator contain at least one element. May be <code>null</code> which is equivalent to passing an empty string.
	 * @param function
	 *            the function that is used to compute the string representation of a single element. May not be
	 *            <code>null</code>.
	 * @return the string representation of the iterator's elements. Never <code>null</code>.
	 */
	public static <T> String join(Iterator<T> iterator, CharSequence before, CharSequence separator, CharSequence after,
			Functions.Function1<? super T, ? extends CharSequence> function) {
		if (function == null)
			throw new NullPointerException("function");
		StringBuilder result = new StringBuilder();
		boolean notEmpty = iterator.hasNext(); 
		if (notEmpty && before != null)
			result.append(before);
		while (iterator.hasNext()) {
			T next = iterator.next();
			CharSequence elementToString = function.apply(next);
			result.append(elementToString);
			if (iterator.hasNext() && separator != null)
				result.append(separator);
		}
		if (notEmpty && after != null)
			result.append(after);
		return result.toString();
	}

	/**
	 * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns
	 * {@code true} if {@code iterator} and {@code other} contain the same number of elements and every element of
	 * {@code iterator} is equal to the corresponding element of {@code other}.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterators.</p>
	 * 
	 * @param iterator
	 *            an iterator. May not be <code>null</code>.
	 * @param other
	 *            an iterator. May not be <code>null</code>.
	 * @return <code>true</code> if the two iterators contain equal elements in the same order.
	 */
	public static boolean elementsEqual(Iterator<?> iterator, Iterator<?> other) {
		return Iterators.elementsEqual(iterator, other);
	}
	
	/**
	 * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns
	 * {@code true} if {@code iterator} and {@code iterable} contain the same number of elements and every element of
	 * {@code iterator} is equal to the corresponding element of {@code iterable}.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterators.</p>
	 * 
	 * @param iterator
	 *            an iterator. May not be <code>null</code>.
	 * @param iterable
	 *            an iterable. May not be <code>null</code>.
	 * @return <code>true</code> if the two iterators contain equal elements in the same order.
	 */
	public static boolean elementsEqual(Iterator<?> iterator, Iterable<?> iterable) {
		return Iterators.elementsEqual(iterator, iterable.iterator());
	}

	/**
	 * Determines if the given iterator is <code>null</code> or contains no elements.
	 * 
	 * @param iterator
	 *            the to-be-queried iterator. May be <code>null</code>.
	 * @return {@code true} if the iterator is <code>null</code> or contains no elements
	 */
	public static boolean isNullOrEmpty(Iterator<?> iterator) {
		return iterator == null || isEmpty(iterator);
	}

	/**
	 * Determines if the given iterator contains no elements.
	 * 
	 * @param iterator
	 *            the to-be-queried iterator. May not be <code>null</code>.
	 * @return {@code true} if the iterator contains no elements
	 * @see #isNullOrEmpty(Iterator)
	 */
	public static boolean isEmpty(Iterator<?> iterator) {
		return !iterator.hasNext();
	}

	/**
	 * Returns the number of elements in {@code iterator}.
	 * The given iterator is left exhausted.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return the number of elements in {@code iterator}.
	 */
	public static int size(Iterator<?> iterator) {
		return Iterators.size(iterator);
	}

	/**
	 * <p>
	 * Applies the combinator {@code function} to all elements of the iterator in turn.
	 * </p>
	 * <p>
	 * One of the function parameters is an element of the iterator, and the other is the result of previous application
	 * of the function. The seed of the operation is the first element in the iterator. The second value is computed by
	 * applying the function to the seed together with the second element of the iterator. The third value is computed
	 * from the previous result together with the third element and so on. In other words, the previous result of each
	 * step is taken and passed together with the next element to the combinator function.
	 * </p>
	 * <p>
	 * If the iterator is empty, <code>null</code> is returned.
	 * </p>
	 * <p>
	 * More formally, given an iterator {@code [a, b, c, d]} and a function {@code f}, the result of {@code reduce} is
	 * <code>f(f(f(a, b), c), d)</code>
	 * </p>
	 * 
	 * @param iterator
	 *            the to-be-reduced iterator. May not be <code>null</code>.
	 * @param function
	 *            the combinator function. May not be <code>null</code>.
	 * @return the last result of the applied combinator function or <code>null</code> for the empty input.
	 */
	public static <T> T reduce(Iterator<? extends T> iterator, Function2<? super T, ? super T, ? extends T> function) {
		if (function == null)
			throw new NullPointerException("function");
		if (iterator.hasNext()) {
			T result = iterator.next();
			while (iterator.hasNext()) {
				result = function.apply(result, iterator.next());
			}
			return result;
		} else {
			return null;
		}
	}

	/**
	 * <p>
	 * Applies the combinator {@code function} to all elements of the iterator in turn and uses {@code seed} as the
	 * start value.
	 * </p>
	 * <p>
	 * One of the function parameters is an element of the iterator, and the other is the result of previous application
	 * of the function. The seed of the operation is explicitly passed to {@link #fold(Iterator, Object, org.eclipse.xtext.xbase.lib.Functions.Function2)
	 * fold}. The first computed value is the result of the applied function for {@code seed} and the first element of
	 * the iterator. This intermediate result together with the second element of the iterator produced the next result
	 * and so on.
	 * </p>
	 * <p>
	 * {@link #fold(Iterator, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold} is similar to {@link #reduce(Iterator, org.eclipse.xtext.xbase.lib.Functions.Function2) reduce} but
	 * allows a {@code seed} value and the combinator {@code function} may be asymmetric. It takes {@code T and R} and
	 * returns {@code R}.
	 * <p>
	 * If the iterator is empty, <code>seed</code> is returned.
	 * </p>
	 * <p>
	 * More formally, given an iterator {@code [a, b, c, d]}, a seed {@code initial} and a function {@code f}, the
	 * result of {@code fold} is <code>f(f(f(f(initial, a), b), c), d)</code>
	 * </p>
	 * 
	 * @param iterator
	 *            the to-be-folded iterator. May not be <code>null</code>.
	 * @param seed
	 *            the initial value. May be <code>null</code>.
	 * @param function
	 *            the combinator function. May not be <code>null</code>.
	 * @return the last result of the applied combinator function or <code>seed</code> for the empty input.
	 */
	public static <T, R> R fold(Iterator<T> iterator, R seed, Function2<? super R, ? super T, ? extends R> function) {
		R result = seed;
		while (iterator.hasNext()) {
			result = function.apply(result, iterator.next());
		}
		return result;
	}

	/**
	 * Returns a list that contains all the entries of the given iterator in the same order. 
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return a list with the same entries as the given iterator. Never <code>null</code>.
	 */
	public static <T> List<T> toList(Iterator<? extends T> iterator) {
		return Lists.newArrayList(iterator);
	}

	/**
	 * Returns a set that contains all the unique entries of the given iterator in the order of their appearance. 
	 * The result set is a copy of the iterator with stable order.
	 * 
	 * @param iterator
	 *            the iterator. May not be <code>null</code>.
	 * @return a set with the unique entries of the given iterator. Never <code>null</code>.
	 */
	public static <T> Set<T> toSet(Iterator<? extends T> iterator) {
		return Sets.newLinkedHashSet(toIterable(iterator));
	}

	/**
	 * Returns a map for which the {@link Map#values} are computed by the given function, and each key is an element in
	 * the given {@code keys}. If the iterator contains equal keys more than once, the last one will be contained in the
	 * map. The map is computed eagerly. That is, subsequent changes in the keys are not reflected by the map.
	 * The key iterator is left exhausted.
	 * 
	 * @param keys
	 *            the keys to use when constructing the {@code Map}. May not be <code>null</code>.
	 * @param computeValues
	 *            the function used to produce the values for each key. May not be <code>null</code>.
	 * @return a map mapping each entry in the given iterator to the corresponding result when evaluating the function
	 *         {@code computeValues}.
	 */
	public static <K, V> Map<K, V> toInvertedMap(Iterator<? extends K> keys, Function1<? super K, V> computeValues) {
		Map<K, V> result = Maps.newLinkedHashMap();
		while(keys.hasNext()) {
			K k = keys.next();
			result.put(k, computeValues.apply(k));
		}
		return result;
	}

	/**
	 * Returns a map for which the {@link Map#values} are the given elements in the given order, and each key is the
	 * product of invoking a supplied function {@code computeKeys} on its corresponding value. If the function produces
	 * the same key for different values, the last one will be contained in the map. The value iterator is left exhausted.
	 * 
	 * @param values
	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
	 * @param computeKeys
	 *            the function used to produce the key for each value. May not be <code>null</code>.
	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
	 *         iterator to that value
	 */
	public static <K, V> Map<K, V> toMap(Iterator<? extends V> values, Function1<? super V, K> computeKeys) {
		if (computeKeys == null)
			throw new NullPointerException("computeKeys");
		Map<K, V> result = Maps.newLinkedHashMap();
		while(values.hasNext()) {
			V v = values.next();
			result.put(computeKeys.apply(v), v);
		}
		return result;
	}
	
	/**
	 * Returns a map for which the {@link Map#values} are the product of invoking supplied function {@code computeValues} 
	 * on input iterable elements, and each key is the product of invoking a supplied function {@code computeKeys} on same elements. 
	 * If the function produces the same key for different values, the last one will be contained in the map. The input iterator is left exhausted.
	 * 
	 * @param inputs
	 *            the elements to use when constructing the {@code Map}. May not be <code>null</code>.
	 * @param computeKeys
	 *            the function used to produce the key for each value. May not be <code>null</code>.
	 * @param computeValues
	 *            the function used to produce the values for each key. May not be <code>null</code>.
	 * @return a map mapping the result of evaluating the functions {@code keyFunction} and {@code computeValues} on each value in the input
	 *         iterator to that value
	 */
	public static <T, K, V> Map<K, V> toMap(Iterator<? extends T> inputs, Function1<? super T, K> computeKeys, Function1<? super T, V> computeValues) {
        if (computeKeys == null)
            throw new NullPointerException("computeKeys");
        if (computeValues == null)
            throw new NullPointerException("computeValues");
        Map<K, V> result = Maps.newLinkedHashMap();
        while(inputs.hasNext()) {
            T t = inputs.next();
            result.put(computeKeys.apply(t), computeValues.apply(t));
        }
        return result;
    }
	
	
	
	/**
	 * Returns a map for which the {@link Map#values} is a collection of lists, where the elements in the list will 
	 * appear in the order as they appeared in the iterator. Each key is the product of invoking the supplied 
	 * function {@code computeKeys} on its corresponding value. So a key of that map groups a list of values for 
	 * which the function produced exactly that key. The value iterator is left exhausted.
	 * 
	 * @param values
	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
	 * @param computeKeys
	 *            the function used to produce the key for each value. May not be <code>null</code>.
	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
	 *         iterator to that value. As there can be more than one value mapped by a key, the mapping result is is a
	 *         list of values.
	 * @since 2.7
	 */
	public static <K, V> Map<K, List<V>> groupBy(Iterator<? extends V> values,
			Function1<? super V, ? extends K> computeKeys) {
		if (computeKeys == null)
			throw new NullPointerException("computeKeys");
		Map<K, List<V>> result = Maps.newLinkedHashMap();
		while(values.hasNext()) {
			V v = values.next();
			K key = computeKeys.apply(v);
			List<V> grouped = result.get(key);
			if (grouped == null) {
				grouped = new ArrayList<V>();
				result.put(key, grouped);
			}
			grouped.add(v);
		}
		return result;
	}	

	/**
	 * Returns an Iterator containing all elements starting from the head of the source up to and excluding the first
	 * element that violates the predicate. The resulting Iterator is a lazily computed view, so any modifications to the
	 * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()}
	 * 
	 * @param iterator
	 *            the elements from which to take. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate which decides whether to keep taking elements. May not be <code>null</code>.
	 * @return the taken elements
	 * @since 2.7
	 */
	public static <T> Iterator<T> takeWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		if (predicate == null)
			throw new NullPointerException("predicate");
		return new AbstractIterator<T>() {
			@Override
			protected T computeNext() {
				if (!iterator.hasNext())
					return endOfData();
				T next = iterator.next();
				if (predicate.apply(next)) {
					return next;
				} else {
					return endOfData();
				}
			}
		};
	}

	/**
	 * Returns an Iterator containing all elements starting from the first element for which the drop-predicate returned
	 * false. The resulting Iterator is a lazily computed view, so any modifications to the
	 * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()}
	 * 
	 * @param iterator
	 *            the elements from which to drop. May not be <code>null</code>.
	 * @param predicate
	 *            the predicate which decides whether to keep dropping elements. May not be <code>null</code>.
	 * @return the remaining elements after dropping
	 * @since 2.7
	 */
	public static <T> Iterator<T> dropWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		if (predicate == null)
			throw new NullPointerException("predicate");
		return new AbstractIterator<T>() {
			private boolean headFound = false;

			@Override
			protected T computeNext() {
				while (!headFound) {
					if (!iterator.hasNext())
						return endOfData();
					T next = iterator.next();
					if (!predicate.apply(next)) {
						headFound = true;
						return next;
					}
				}
				if (iterator.hasNext()) {
					return iterator.next();
				} else {
					return endOfData();
				}
			}
		};
	}

	/**
	 * Returns an Iterator of Pairs where the nth pair is created by taking the nth element of the source as the value
	 * and its 0-based index as the key. E.g.
	 * <code>zipWitIndex(#["a", "b", "c"]) == #[(0, "a"), (1, "b"), (2, "c")]</code>
	 * 
	 * If the index would overflow, {@link Integer#MAX_VALUE} is returned for all subsequent elements.
	 * 
	 * The resulting Iterator is a lazily computed view, so any modifications to the underlying Iterator will be
	 * reflected on iteration. The result does not support {@link Iterator#remove()}
	 * 
	 * @param iterator
	 *            the elements. May not be <code>null</code>.
	 * @return the zipped result
	 * @since 2.7
	 */
	public static <A> Iterator<Pair<Integer, A>> indexed(final Iterator<? extends A> iterator) {
		if (iterator == null)
			throw new NullPointerException("iterator");
		return new AbstractIterator<Pair<Integer, A>>() {
			int i = 0;
			@Override
			protected Pair<Integer, A> computeNext() {
				if (iterator.hasNext()) {
					Pair<Integer, A> next = new Pair<Integer, A>(i, iterator.next());
					if (i != Integer.MAX_VALUE)
						i++;
					return next;
				} else {
					return endOfData();
				}
			}
		};
	}

	/**
	 * Finds the minimum of the given elements according to their natural ordering. If there are several mimina, the
	 * first one will be returned.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the mutually comparable elements. May not be <code>null</code>.
	 * @return the minimum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T extends Comparable<? super T>> T min(final Iterator<T> iterator) {
		return min(iterator, Ordering.natural());
	}

	/**
	 * Finds the element that yields the minimum value when passed to <code>compareBy</code>. If there are several
	 * maxima, the first one will be returned.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the elements to find the minimum of. May not be <code>null</code>.
	 * @param compareBy
	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
	 * @return the minimum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T, C extends Comparable<? super C>> T minBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) {
		if (compareBy == null)
			throw new NullPointerException("compareBy");
		return min(iterator, new KeyComparator<T, C>(compareBy));
	}
	
	/**
	 * Finds the mininmum element according to <code>comparator</code>. If there are several minima, the first one will
	 * be returned.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the elements to find the minimum of. May not be <code>null</code>.
	 * @param comparator
	 *            the comparison function. May not be <code>null</code>.
	 * @return the minimum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T> T min(final Iterator<T> iterator, Comparator<? super T> comparator) {
		if (comparator == null)
			throw new NullPointerException("comparator");
		T min = iterator.next();
		while (iterator.hasNext()) {
			T element = iterator.next();
			min = comparator.compare(min, element) <= 0 ? min : element;
		}
		return min;
	}

	/**
	 * Finds the maximum of the elements according to their natural ordering. If there are several maxima, the first one
	 * will be returned.
	 * 
     * <p>Note that this will advance or even exhaust the given iterator.</p>
     * 
	 * @param iterator
	 *            the mutually comparable elements. May not be <code>null</code>.
	 * @return the maximum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T extends Comparable<? super T>> T max(final Iterator<T> iterator) {
		return max(iterator, Ordering.natural());
	}

	/**
	 * Finds the element that yields the maximum value when passed to <code>compareBy</code> If there are several
	 * maxima, the first one will be returned.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the elements to find the maximum of. May not be <code>null</code>.
	 * @param compareBy
	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
	 * @return the maximum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T, C extends Comparable<? super C>> T maxBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) {
		if (compareBy == null)
			throw new NullPointerException("compareBy");
		return max(iterator, new KeyComparator<T, C>(compareBy));
	}

	/**
	 * Finds the maximum element according to <code>comparator</code>. If there are several maxima, the first one will
	 * be returned.
	 * 
	 * <p>Note that this will advance or even exhaust the given iterator.</p>
	 * 
	 * @param iterator
	 *            the elements to find the maximum of. May not be <code>null</code>.
	 * @param comparator
	 *            the comparison function. May not be <code>null</code>.
	 * @return the maximum
	 * @throws NoSuchElementException
	 *             if the iterator is empty
	 * @since 2.7
	 */
	public static <T> T max(final Iterator<T> iterator, Comparator<? super T> comparator) {
		if (comparator == null)
			throw new NullPointerException("comparator");
		T max = iterator.next();
		while (iterator.hasNext()) {
			T element = iterator.next();
			max = comparator.compare(max, element) >= 0 ? max : element;
		}
		return max;
	}

	/**
	 * Returns <tt>true</tt> if this Iterator contains the specified element.
	 * More formally, returns <tt>true</tt> if and only if this Iterator
	 * contains at least one element <tt>e</tt> such that
	 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
	 * 
	 * <p>
	 * Note that this will advance or even exhaust the given iterator.
	 * </p>
	 *
	 * @param iterator 
	 * 			the elements to test
	 * @param o 
	 * 			element whose presence in this Iterator is to be tested
	 * @return <tt>true</tt> if this Iterator contains the specified element
	 */
	public static boolean contains(Iterator<?> iterator, Object o) {
		while (iterator.hasNext()) {
			if (Objects.equals(o, iterator.next())) {
				return true;
			}
		}
		return false;
	}
}
