/*******************************************************************************
 * Copyright (c) 2011, 2017 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.tests.lib;

import static com.google.common.collect.Lists.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.xtext.xbase.lib.Functions;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IteratorExtensions;
import org.eclipse.xtext.xbase.lib.Pair;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.junit.Assert;
import org.junit.Test;

import com.google.common.collect.Iterators;

/**
 * @author Sven Efftinge - Initial contribution and API
 * @author Karsten Thoms - testMap, testFlatMap
 */
public class IteratorExtensionsTest extends BaseIterablesIteratorsTest<Iterator<Integer>> {
	
	@Test public void testToIterable() throws Exception {
		ArrayList<String> list = newArrayList("A","B");
		for (String s : IteratorExtensions.toIterable(list.iterator())) {
			assertTrue(list.contains(s));
		}
	}
	
	@Override
	protected boolean canIterateTwice() {
		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Iterator<Integer>[] testData(Integer... elements) {
		return new Iterator[] { Iterators.forArray(elements) };
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected Iterator<Integer>[] nullableTestData(Integer... elements) {
		return new Iterator[] { Iterators.forArray(elements) };
	}

	@Override
	protected Iterator<Integer> dummy() {
		return Collections.<Integer>emptyList().iterator();
	}

	@Override
	protected boolean is(Iterator<Integer> input, Integer... elements) {
		return Iterators.elementsEqual(input, Iterators.forArray(elements));
	}

	@Override
	protected Iterator<Integer> operator_plus(Iterator<Integer> first, Iterator<Integer> second) {
		return IteratorExtensions.operator_plus(first, second);
	}

	@Override
	protected Integer findFirst(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
		return IteratorExtensions.findFirst(input, filter);
	}

	@Override
	protected Integer findLast(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
		return IteratorExtensions.findLast(input, filter);
	}

	@Override
	protected Integer last(Iterator<Integer> input) {
		return IteratorExtensions.last(input);
	}

	@Override
	protected Integer head(Iterator<Integer> input) {
		return IteratorExtensions.head(input);
	}
	
	@Override
	protected void forEach(Iterator<Integer> input, Procedure2<Integer, Integer> proc) {
		IteratorExtensions.forEach(input, proc);
	}
	
	@Override
	protected Iterator<Integer> takeWhile(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
		return IteratorExtensions.takeWhile(input, filter);
	}
	
	@Override
	protected Iterator<Integer> dropWhile(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
		return IteratorExtensions.dropWhile(input, filter);
	}
	
	@Override
	protected Integer max(Iterator<Integer> input) {
		return IteratorExtensions.max(input);
	}
	
	@Override
	protected Integer max(Iterator<Integer> input, Comparator<? super Integer> comparator) {
		return IteratorExtensions.max(input, comparator);
	}
	
	@Override
	protected Integer maxBy(Iterator<Integer> input, Function1<? super Integer, String> compareBy) {
		return IteratorExtensions.maxBy(input, compareBy);
	}
	
	@Override
	protected Integer min(Iterator<Integer> input) {
		return IteratorExtensions.min(input);
	}
	
	@Override
	protected Integer min(Iterator<Integer> input, Comparator<? super Integer> comparator) {
		return IteratorExtensions.min(input, comparator);
	}
	
	@Override
	protected Integer minBy(Iterator<Integer> input, Function1<? super Integer, String> compareBy) {
		return IteratorExtensions.minBy(input, compareBy);
	}
	
	@Test public void testIndexed() {
		Iterator<Pair<Integer, String>> result = IteratorExtensions.indexed(newArrayList("foo", "bar").iterator());
		assertEquals(new Pair<Integer, String>(0, "foo"), result.next());
		assertEquals(new Pair<Integer, String>(1, "bar"), result.next());
		assertFalse(result.hasNext());
	}
	
	@Test
	public void testToMap() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		pairs.add(new Pair<Integer, String>(1, "A"));
		pairs.add(new Pair<Integer, String>(1, "a"));
		pairs.add(new Pair<Integer, String>(2, "B"));
		pairs.add(new Pair<Integer, String>(2, "b"));
		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {

			@Override
			public Integer apply(Pair<Integer, String> p) {
				return p.getKey();
			}
		};
		Map<Integer, Pair<Integer, String>> map = IteratorExtensions.toMap(pairs.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 2, map.size());
		Assert.assertTrue("Contains 1 as key", map.keySet().contains(1));
		Assert.assertEquals("Contains entry 1->a for key 1", map.get(1), new Pair<Integer, String>(1, "a"));
		Assert.assertTrue("Contains 2 as key", map.keySet().contains(2));
		Assert.assertEquals("Contains entry 2->b for key 2", map.get(2), new Pair<Integer, String>(2, "b"));
	}

	@Test
	public void testToMap__WhenEmptyList() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {

			@Override
			public Integer apply(Pair<Integer, String> p) {
				return p.getKey();
			}
		};
		Map<Integer, Pair<Integer, String>> map = IteratorExtensions.toMap(pairs.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 0, map.size());
	}

	@Test
	public void testToMap__WhenCalculatedKeyNull() {
		List<String> names = new ArrayList<String>();
		names.add("Mueller");
		names.add("Schneider");
		names.add("Schmidt");
		names.add("Koch");
		Function1<String, String> computeKeys = new Function1<String, String>() {

			@Override
			public String apply(String p) {
				return p.contains("y") ? "y" : null;
			}
		};
		Map<String, String> map = IteratorExtensions.toMap(names.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 1, map.size());
		Assert.assertTrue("Contains null as key", map.keySet().contains(null));
		Assert.assertEquals("Contains entry Koch for key null", "Koch", map.get(null));
	}

	@Test
	public void testToMap__WhenNoValuesForKey() {
		List<String> names = new ArrayList<String>();
		names.add("Mueller");
		names.add("Schneider");
		names.add("Schmidt");
		names.add("Koch");
		Function1<String, Boolean> computeKeys = new Function1<String, Boolean>() {

			@Override
			public Boolean apply(String p) {
				return p.contains("y");
			}
		};
		Map<Boolean, String> map = IteratorExtensions.toMap(names.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 1, map.size());
		Assert.assertTrue("Contains FALSE as key", map.keySet().contains(Boolean.FALSE));
		Assert.assertTrue("Contains entry Mueller for key FALSE", map.get(Boolean.FALSE).equals("Koch"));
		Assert.assertNull("Contains no entry for key Boolean.TRUE", map.get(Boolean.TRUE));
	}

	@Test(expected = NullPointerException.class)
	public void testToMap__WhenFunctionNull() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		Function1<Pair<Integer, String>, Integer> computeKeys = null;
		IteratorExtensions.toMap(pairs.iterator(), computeKeys);
	}	
	
	@Test
	public void testGroupBy() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		pairs.add(new Pair<Integer, String>(1, "A"));
		pairs.add(new Pair<Integer, String>(1, "a"));
		pairs.add(new Pair<Integer, String>(2, "B"));
		pairs.add(new Pair<Integer, String>(2, "b"));
		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {

			@Override
			public Integer apply(Pair<Integer, String> p) {
				return p.getKey();
			}
		};
		Map<Integer, List<Pair<Integer, String>>> map = IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 2, map.size());
		Assert.assertTrue("Contains 1 as key", map.keySet().contains(1));
		Assert.assertEquals("Contains 2 entries for key 1", 2, map.get(1).size());
		Assert.assertEquals("Contains entry 1->A for key 1", new Pair<Integer, String>(1, "A"), map.get(1).get(0));
		Assert.assertEquals("Contains entry 1->a for key 1", new Pair<Integer, String>(1, "a"), map.get(1).get(1));
		Assert.assertTrue("Contains 2 as key", map.keySet().contains(2));
		Assert.assertEquals("Contains 2 entries for key 2", 2, map.get(2).size());
		Assert.assertEquals("Contains entry 2->B for key 2", new Pair<Integer, String>(2, "B"), map.get(2).get(0));
		Assert.assertEquals("Contains entry 2->b for key 2", new Pair<Integer, String>(2, "b"), map.get(2).get(1));
	}

	@Test
	public void testGroupBy__WhenEmptyList() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {

			@Override
			public Integer apply(Pair<Integer, String> p) {
				return p.getKey();
			}
		};
		Map<Integer, List<Pair<Integer, String>>> map = IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 0, map.size());
	}

	@Test
	public void testGroupBy__WhenCalculatedKeyNull() {
		List<String> names = new ArrayList<String>();
		names.add("Mueller");
		names.add("Schneider");
		names.add("Schmidt");
		names.add("Koch");
		Function1<String, String> computeKeys = new Function1<String, String>() {

			@Override
			public String apply(String p) {
				return p.contains("y") ? "y" : null;
			}
		};
		Map<String, List<String>> map = IteratorExtensions.groupBy(names.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 1, map.size());
		Assert.assertTrue("Contains null as key", map.keySet().contains(null));
		Assert.assertEquals("Contains 4 entries for key null", 4, map.get(null).size());
	}

	@Test
	public void testGroupBy__WhenNoValuesForKey() {
		List<String> names = new ArrayList<String>();
		names.add("Mueller");
		names.add("Schneider");
		names.add("Schmidt");
		names.add("Koch");
		Function1<String, Boolean> computeKeys = new Function1<String, Boolean>() {

			@Override
			public Boolean apply(String p) {
				return p.contains("y");
			}
		};
		Map<Boolean, List<String>> map = IteratorExtensions.groupBy(names.iterator(), computeKeys);
		Assert.assertEquals("Expected grouped map size", 1, map.size());
		Assert.assertTrue("Contains FALSE as key", map.keySet().contains(Boolean.FALSE));
		Assert.assertEquals("Contains 4 entries for key Boolean.FALSE", 4, map.get(Boolean.FALSE).size());
		Assert.assertTrue("Contains entry Mueller for key FALSE", map.get(Boolean.FALSE).contains("Mueller"));
		Assert.assertNull("Contains no entry for key Boolean.TRUE", map.get(Boolean.TRUE));
	}

	@Test(expected = NullPointerException.class)
	public void testGroupBy__WhenFunctionNull() {
		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
		Function1<Pair<Integer, String>, Integer> computeKeys = null;
		IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
	}

	@Test public void testReject() {
		Function1<Integer, Boolean> function = new Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return p % 2 == 0;
			}
		};
		assertEquals(newArrayList(1,3,5),newArrayList(IteratorExtensions.reject(newArrayList(1,2,3,4,5).iterator(), function)));
		Function1<Integer, Boolean> functionNullSafe = new Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return p == null || p % 2 == 0;
			}
		};
		assertEquals(newArrayList(1,5),newArrayList(IteratorExtensions.reject(newArrayList(1,2,null,4,5).iterator(), functionNullSafe)));
		try {
			newArrayList(IteratorExtensions.reject(null, function));
			fail("NullPointerException expected");
		} catch (NullPointerException e) {
			// expected NPE
		}
		try {
			newArrayList(IteratorExtensions.reject(newArrayList(1,2,3).iterator(), null));
			fail("NullPointerException expected");
		} catch (NullPointerException e) {
			// expected NPE
		}
		Function1<Integer, Boolean> brokenFunction = new Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return null;
			}
		};
		try {
			newArrayList(IteratorExtensions.reject(newArrayList(1,2,3).iterator(), brokenFunction));
			fail("NullPointerException expected");
		} catch (NullPointerException e) {
			// expected NPE
		}
	}

	@Test public void testMap () {
		ArrayList<String> list = newArrayList("foo", "bar");
		
		final Functions.Function1<String, String> function = new Functions.Function1<String, String>() {
			@Override
			public String apply(String p) {
				return "Hello "+p;
			}
		};
		
		assertEquals(newArrayList("Hello foo", "Hello bar"), newArrayList(IteratorExtensions.map(list.iterator(), function)));

	
		// test that the returned iterator supports remove on the underyling list
		// therefore we need a function that maps to the same object contained in the list
		final Functions.Function1<String, String> functionForRemove = new Functions.Function1<String, String>() {
			@Override
			public String apply(String p) {
				return "foo".equals(p) ? p : "Hello "+p;
			}
		};

		assertTrue(list.contains("foo"));
		assertEquals(2, list.size());
		assertEquals(newArrayList("foo", "Hello bar"), newArrayList(IteratorExtensions.map(list.iterator(), functionForRemove)));
		Iterator<String> iterator = IteratorExtensions.map(list.iterator(), functionForRemove);
		iterator.next();
		iterator.remove();
		
		assertTrue(!list.contains("foo"));
		assertEquals(1, list.size());
	}

	@Test public void testFlatMap () {
		ArrayList<String> list = newArrayList("foo", "bar");
		
		final Functions.Function1<String, Iterator<String>> function = new Functions.Function1<String, Iterator<String>>() {
			@Override
			public Iterator<String> apply(String p) {
				return newArrayList("Hello", p).iterator();
			}
		};
		assertEquals(newArrayList("Hello", "foo", "Hello", "bar"), newArrayList(IteratorExtensions.flatMap(list.iterator(), function)));
	}
	
	@Test public void testContains() {
		ArrayList<String> list = newArrayList("element1", "element2", "element3", null);
		
		assertTrue(IteratorExtensions.contains(list.iterator(), "element3"));
		assertTrue(IteratorExtensions.contains(list.iterator(), new String("element3")));
		
		assertTrue(IteratorExtensions.contains(list.iterator(), null));
		
		assertFalse(IteratorExtensions.contains(list.iterator(), "element4"));
		assertFalse(IteratorExtensions.contains(list.iterator(), new String("element4")));
	}
}
