/*******************************************************************************
 * 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.tests.lib;

import java.util.Comparator;
import java.util.NoSuchElementException;

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

import com.google.common.collect.Ordering;

/**
 * @author Sebastian Zarnekow - Initial contribution and API
 */
public abstract class BaseIterablesIteratorsTest<IterableOrIterator> extends Assert {

	protected Integer first = Integer.valueOf(1);
	protected Integer second = Integer.valueOf(2);
	protected Integer third = Integer.valueOf(3);
	protected Integer forth = Integer.valueOf(4);
	protected Integer fifth = Integer.valueOf(5);
	
	protected abstract IterableOrIterator[] testData(Integer... elements);
	protected abstract IterableOrIterator[] nullableTestData(Integer... elements);
	protected abstract IterableOrIterator dummy();
	protected abstract boolean is(IterableOrIterator input, Integer... elements);

	protected abstract IterableOrIterator operator_plus(IterableOrIterator first, IterableOrIterator second);
	protected boolean canIterateTwice() {
		return true;
	}
	
	@Test public void testOperatorPlus_Same() {
		IterableOrIterator[] data = testData(first, second);
		for(int i = 0;i < data.length; i++) {
			if (canIterateTwice())
				assertTrue(is(operator_plus(data[i], data[i]), first, second, first, second));
			else
				assertTrue(is(operator_plus(data[i], data[i]), first, second));
		}
	}
	
	@Test public void testOperatorPlus() {
		IterableOrIterator[] firstData = testData(first, second);
		IterableOrIterator[] secondData = testData(third, forth);
		for(int i = 0;i < firstData.length; i++) {
			assertTrue(is(operator_plus(firstData[i], secondData[i]), first, second, third, forth));
		}
	}
	
	@Test public void testOperatorPlus_NPE_left() {
		try {
			operator_plus(null, dummy());
			fail("expected NullPointerException");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	@Test public void testOperatorPlus_NPE_right() {
		try {
			operator_plus(dummy(), null);
			fail("expected NullPointerException");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract Integer findFirst(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
	
	@Test public void testFindFirst_empty() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return true;
			}
		};
		for(IterableOrIterator testMe: testData()) {
			Integer last = findFirst(testMe, filter);
			assertNull("empty input yields null", last);
		}
	}
	
	@Test public void testFindFirst_noMatch() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return false;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findFirst(testMe, filter);
			assertNull("unmatched input yields null", last);
		}
	}
	
	@Test public void testFindFirst_allMatches() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return true;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findFirst(testMe, filter);
			assertEquals(first, last);
		}
	}
	
	@Test public void testFindFirst_oneMatch() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return second.equals(p);
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findFirst(testMe, filter);
			assertEquals(second, last);
		}
	}

	@Test public void testFindFirst_exceptionInFilter() {
		final RuntimeException expectedException = new RuntimeException();
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				throw expectedException;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			try {
				findFirst(testMe, filter);
				fail("expected exception");
			} catch(RuntimeException e) {
				assertSame(expectedException, e);
			}
		}
	}
	
	@Test public void testFindFirst_exceptionInFilter_emptyInput() {
		final RuntimeException expectedException = new RuntimeException();
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				throw expectedException;
			}
		};
		for(IterableOrIterator testMe: testData()) {
			assertNull(findFirst(testMe, filter));
		}
	}
	
	@Test public void testFindFirst_NPE_noFilter() {
		for(IterableOrIterator testMe: testData()) {
			try {
				findFirst(testMe, null);
				fail("Expected NPE");
			} catch(NullPointerException npe) {
				// expected
			}
		}
	}
	
	@Test public void testFindFirst_NPE_noInput() {
		try {
			findLast(null, new Functions.Function1<Integer, Boolean>() {
				@Override
				public Boolean apply(Integer p) {
					return true;
				}
			});
			fail("Expected NPE");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract Integer findLast(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
	
	@Test public void testFindLast_empty() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return true;
			}
		};
		for(IterableOrIterator testMe: testData()) {
			Integer last = findLast(testMe, filter);
			assertNull("empty input yields null", last);
		}
	}
	
	@Test public void testFindLast_noMatch() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return false;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findLast(testMe, filter);
			assertNull("unmatched input yields null", last);
		}
	}
	
	@Test public void testFindLast_allMatches() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return true;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findLast(testMe, filter);
			assertEquals(third, last);
		}
	}
	
	@Test public void testFindLast_oneMatch() {
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return second.equals(p);
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = findLast(testMe, filter);
			assertEquals(second, last);
		}
	}

	@Test public void testFindLast_exceptionInFilter() {
		final RuntimeException expectedException = new RuntimeException();
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				throw expectedException;
			}
		};
		for(IterableOrIterator testMe: testData(first, second, third)) {
			try {
				findLast(testMe, filter);
				fail("expected exception");
			} catch(RuntimeException e) {
				assertSame(expectedException, e);
			}
		}
	}
	
	@Test public void testFindLast_exceptionInFilter_emptyInput() {
		final RuntimeException expectedException = new RuntimeException();
		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				throw expectedException;
			}
		};
		for(IterableOrIterator testMe: testData()) {
			Integer last = findLast(testMe, filter);
			assertEquals(null, last);
		}
	}
	
	@Test public void testFindLast_NPE_noFilter() {
		for(IterableOrIterator testMe: testData()) {
			try {
				findLast(testMe, null);
				fail("Expected NPE");
			} catch(NullPointerException npe) {
				// expected
			}
		}
	}
	
	@Test public void testFindLast_NPE_noInput() {
		try {
			findLast(null, new Functions.Function1<Integer, Boolean>() {
				@Override
				public Boolean apply(Integer p) {
					return true;
				}
			});
			fail("Expected NPE");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract Integer last(IterableOrIterator input);
	
	@Test public void testLast_empty() {
		for(IterableOrIterator testMe: testData()) {
			Integer last = last(testMe);
			assertNull("empty input yields null", last);
		}
	}
	
	@Test public void testLast_oneEntry() {
		for(IterableOrIterator testMe: testData(first)) {
			Integer last = last(testMe);
			assertEquals(first, last);
		}
	}
	
	@Test public void testLast_entryIsNull() {
		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
			Integer last = last(testMe);
			assertEquals(null, last);
		}
	}
	
	@Test public void testLast_moreEntries() {
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer last = last(testMe);
			assertEquals(third, last);
		}
	}
	
	@Test public void testLast_NPE() {
		try {
			last(null);
			fail("expeced NPE");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract Integer head(IterableOrIterator input);
	
	@Test public void testHead_empty() {
		for(IterableOrIterator testMe: testData()) {
			Integer head = head(testMe);
			assertNull("empty input yields null", head);
		}
	}
	
	@Test public void testHead_oneEntry() {
		for(IterableOrIterator testMe: testData(first)) {
			Integer head = head(testMe);
			assertEquals(first, head);
		}
	}
	
	@Test public void testHead_entryIsNull() {
		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
			Integer head = head(testMe);
			assertEquals(null, head);
		}
	}
	
	@Test public void testHead_moreEntries() {
		for(IterableOrIterator testMe: testData(first, second, third)) {
			Integer head = head(testMe);
			assertEquals(first, head);
		}
	}
	
	@Test public void testHead_NPE() {
		try {
			head(null);
			fail("expeced NPE");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract void forEach(IterableOrIterator input, Procedures.Procedure2<Integer, Integer> proc);
	
	static class ForEachLoopCounter implements Procedures.Procedure2<Integer, Integer> {

		private int expectedIndex = 0;
		private final Integer[] values;
		
		ForEachLoopCounter(Integer... values) {
			this.values = values;
		}
		
		@Override
		public void apply(Integer value, Integer index) {
			assertEquals(expectedIndex, index.intValue());
			assertEquals(values[expectedIndex], value);
			expectedIndex++;
		}
		
	}
	
	@Test public void testForEachWithIndex_empty() {
		for(IterableOrIterator testMe: testData()) {
			ForEachLoopCounter counter = new ForEachLoopCounter();
			forEach(testMe, counter);
			assertEquals(0, counter.expectedIndex);
		}
	}
	
	@Test public void testForEachWithIndex_empty_noProcedure() {
		for(IterableOrIterator testMe: testData()) {
			try {
				forEach(testMe, null);
				fail("expeced NPE");
			} catch(NullPointerException e) {
				// expected
			}
		}
	}
	
	@Test public void testForEachWithIndex_oneEntry() {
		for(IterableOrIterator testMe: testData(first)) {
			ForEachLoopCounter counter = new ForEachLoopCounter(first);
			forEach(testMe, counter);
			assertEquals(1, counter.expectedIndex);
		}
	}
	
	@Test public void testForEachWithIndex_entryIsNull() {
		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
			ForEachLoopCounter counter = new ForEachLoopCounter((Integer)null);
			forEach(testMe, counter);
			assertEquals(1, counter.expectedIndex);
		}
	}
	
	@Test public void testForEachWithIndex_moreEntries() {
		for(IterableOrIterator testMe: testData(first, second, forth)) {
			ForEachLoopCounter counter = new ForEachLoopCounter(first, second, forth);
			forEach(testMe, counter);
			assertEquals(3, counter.expectedIndex);
		}
	}
	
	@Test public void testForEachWithIndex_NPE() {
		try {
			forEach(null, new ForEachLoopCounter());
			fail("expeced NPE");
		} catch(NullPointerException npe) {
			// expected
		}
	}
	
	protected abstract IterableOrIterator takeWhile(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
	protected abstract IterableOrIterator dropWhile(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
	protected abstract Integer min(IterableOrIterator input);
	protected abstract Integer max(IterableOrIterator input);
	protected abstract Integer min(IterableOrIterator input, Comparator<? super Integer> comparator);
	protected abstract Integer max(IterableOrIterator input, Comparator<? super Integer> comparator);
	protected abstract Integer minBy(IterableOrIterator input, Functions.Function1<? super Integer, String> compareBy);
	protected abstract Integer maxBy(IterableOrIterator input, Functions.Function1<? super Integer, String> compareBy);
	
	@Test public void testTakeWhile() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			IterableOrIterator taken = takeWhile(testMe, new Function1<Integer, Boolean>() {
				@Override
				public Boolean apply(Integer p) {
					return p <= 3;
				}
			});
			assertTrue(is(taken, first, second, third));
		}
	}
	
	@Test public void testDropWhile() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			IterableOrIterator tail = dropWhile(testMe, new Function1<Integer, Boolean>() {
				@Override
				public Boolean apply(Integer p) {
					return p <= 3;
				}
			});
			assertTrue(is(tail, forth, fifth));
		}
	}
	
	@Test public void testMinComparable() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer min = min(testMe);
			assertEquals(first, min);
		}
	}
	
	@Test public void testMaxComparable() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer max = max(testMe);
			assertEquals(fifth, max);
		}
	}
	
	@Test(expected = NoSuchElementException.class) 
	public void testMinEmpty() {
		for (IterableOrIterator testMe : testData()) {
			min(testMe);
		}
	}
	
	@Test(expected = NoSuchElementException.class)
	public void testMaxEmpty() {
		for (IterableOrIterator testMe : testData()) {
			max(testMe);
		}
	}
	
	@Test public void testMinComparator() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer min = min(testMe, Ordering.natural().reverse());
			assertEquals(fifth, min);
		}
	}
	
	@Test public void testMaxComparator() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer max = max(testMe, Ordering.natural().reverse());
			assertEquals(first, max);
		}
	}
	
	@Test public void testMinBy() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer min = minBy(testMe, new Function1<Integer, String>() {
				@Override
				public String apply(Integer p) {
					return Integer.toBinaryString(p);
				}
			});
			assertEquals(first, min);
		}
	}
	
	@Test public void testMaxBy() {
		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
			Integer max = maxBy(testMe, new Function1<Integer, String>() {
				@Override
				public String apply(Integer p) {
					return Integer.toBinaryString(p);
				}
			});
			assertEquals(third, max);
		}
	}
}
