/*******************************************************************************
 * 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 static com.google.common.collect.Sets.*;

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

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

import com.google.common.collect.ForwardingCollection;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * @author Sebastian Zarnekow - Initial contribution and API
 * @author Karsten Thoms - testMap, testFlatMap
 */
public class IterableExtensionsTest extends BaseIterablesIteratorsTest<Iterable<Integer>> {

	@Override
	protected Iterable<Integer>[] testData(Integer... elements) {
		@SuppressWarnings("unchecked")
		Iterable<Integer>[] result = new Iterable[] {
			Lists.newArrayList(elements),
			Lists.newLinkedList(Lists.newArrayList(elements)),
			Sets.newLinkedHashSet(Lists.newArrayList(elements)),
			Sets.newTreeSet(Lists.newArrayList(elements))
		};
		return result;
	}
	
	@Override
	protected Iterable<Integer>[] nullableTestData(Integer... elements) {
		@SuppressWarnings("unchecked")
		Iterable<Integer>[] result = new Iterable[] {
			Lists.newArrayList(elements),
			Lists.newLinkedList(Lists.newArrayList(elements)),
			Sets.newLinkedHashSet(Lists.newArrayList(elements)),
//			Sets.newTreeSet(Lists.newArrayList(elements)) null is not allowed
		};
		return result;
	}

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

	@Override
	protected boolean is(Iterable<Integer> input, Integer... elements) {
		return Iterables.elementsEqual(input, Lists.newArrayList(elements));
	}

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

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

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

	@Override
	protected Integer last(Iterable<Integer> input) {
		return IterableExtensions.last(input);
	}

	@Override
	protected Integer head(Iterable<Integer> input) {
		return IterableExtensions.head(input);
	}
	
	@Override
	protected void forEach(Iterable<Integer> input, Procedure2<Integer, Integer> proc) {
		IterableExtensions.forEach(input, proc);
	}
	
	@Override
	protected Iterable<Integer> takeWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
		return IterableExtensions.takeWhile(input, filter);
	}
	
	@Override
	protected Iterable<Integer> dropWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
		return IterableExtensions.dropWhile(input, filter);
	}
	
	@Override
	protected Integer max(Iterable<Integer> input) {
		return IterableExtensions.max(input);
	}
	
	@Override
	protected Integer max(Iterable<Integer> input, Comparator<? super Integer> comparator) {
		return IterableExtensions.max(input, comparator);
	}
	
	@Override
	protected Integer maxBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) {
		return IterableExtensions.maxBy(input, compareBy);
	}
	
	@Override
	protected Integer min(Iterable<Integer> input) {
		return IterableExtensions.min(input);
	}
	
	@Override
	protected Integer min(Iterable<Integer> input, Comparator<? super Integer> comparator) {
		return IterableExtensions.min(input, comparator);
	}
	
	@Override
	protected Integer minBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) {
		return IterableExtensions.minBy(input, compareBy);
	}
	
	@Test public void testJoinWithNull() {
		List<String> list = Lists.newArrayList("a", null, "c");
		String string = IterableExtensions.join(list, ",");
		assertEquals("a,null,c", string);
	}
	
	@Test public void testSortBy() throws Exception {
		List<? extends CharSequence> list = newArrayList("foo","bar","baz");
		List<? extends CharSequence> sorted = IterableExtensions.sortBy(list, new Functions.Function1<CharSequence, String>() {
			@Override
			public String apply(CharSequence p) {
				return p.toString();
			}
		});
		assertNotSame(list, sorted);
		assertEquals(sorted, newArrayList("bar","baz","foo"));
	}
	
	@Test public void testFilterNull() throws Exception {
		Iterator<String> iter = IterableExtensions.filterNull(newArrayList("foo", null, "bar")).iterator();
		assertEquals("foo", iter.next());
		assertEquals("bar", iter.next());
		assertFalse(iter.hasNext());
	}
	
	@Test public void testJoinWithBeforeAndAfter() throws Exception {
		ArrayList<String> list = newArrayList("foo", "bar");
		ArrayList<String> singletonList = newArrayList("foo");
		ArrayList<String> emptylist = new ArrayList<String>();
		
		final Functions.Function1<String, String> function = new Functions.Function1<String, String>() {
			@Override
			public String apply(String p) {
				return p;
			}
		};
		assertEquals("<foo,bar>", IterableExtensions.join(list, "<", ",", ">", function));
		assertEquals("<foo>", IterableExtensions.join(singletonList, "<", ",", ">", function));
		assertEquals("", IterableExtensions.join(emptylist, "<", ",", ">", function));
		
		assertEquals("foo,bar>", IterableExtensions.join(list, null, ",", ">", function));
		assertEquals("foo>", IterableExtensions.join(singletonList, null, ",", ">", function));
		assertEquals("", IterableExtensions.join(emptylist, null, ",", ">", function));
		
		assertEquals("<foobar>", IterableExtensions.join(list, "<", null, ">", function));
		assertEquals("<foo>", IterableExtensions.join(singletonList, "<", null, ">", function));
		assertEquals("", IterableExtensions.join(emptylist, "<", null, ">", function));
		
		assertEquals("<foo,bar", IterableExtensions.join(list, "<", ",", null, function));
		assertEquals("<foo", IterableExtensions.join(singletonList, "<", ",", null, function));
		assertEquals("", IterableExtensions.join(emptylist, "<", ",", null, function));
	}
	
	@Test public void testIndexed() {
		Iterator<Pair<Integer, String>> result = IterableExtensions.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());
	}

	class A {}
	interface C {}
	class B extends A implements C {}
	class D extends A {}

	@Test public void testReject() {
		List<Integer> nullList = new ArrayList<>();
		nullList.add(null);
		List<Object> objects = newArrayList(1, 2, null, 4l, "String");
		assertEquals(newArrayList(1, 2, null, 4l), newArrayList(IterableExtensions.reject(objects, String.class)));
		assertEquals(nullList, newArrayList(IterableExtensions.reject(objects, Object.class)));
		
		List<Integer> integerObjects = newArrayList(1, 2, null, 4);
		assertEquals(nullList, newArrayList(IterableExtensions.reject(integerObjects, Integer.class)));
		
		List<A> bObjects = newArrayList(new B(), new B(), new D());
		assertEquals(0, IterableExtensions.size(IterableExtensions.reject(bObjects, A.class)));
		assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, B.class)));
		assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, C.class)));
		assertEquals(2, IterableExtensions.size(IterableExtensions.reject(bObjects, D.class)));
		
		Function1<Integer, Boolean> function = new Function1<Integer, Boolean>() {
			@Override
			public Boolean apply(Integer p) {
				return p % 2 == 0;
			}
		};
		assertEquals(newArrayList(1,3,5),newArrayList(IterableExtensions.reject(newArrayList(1,2,3,4,5), 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(IterableExtensions.reject(newArrayList(1,2,null,4,5), functionNullSafe)));
		try {
			newArrayList(IterableExtensions.reject(null, function));
			fail("NullPointerException expected");
		} catch (NullPointerException e) {
			// expected NPE
		}
		try {
			Function1<? super Integer, Boolean> nullFn = null;
			newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullFn));
			fail("NullPointerException expected");
		} catch (NullPointerException e) {
			// expected NPE
		}
		try {
			Class<Integer> nullClass = null;
			newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullClass));
			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(IterableExtensions.reject(newArrayList(1,2,3), 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(IterableExtensions.map(list, 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(IterableExtensions.map(list, functionForRemove)));
		Iterator<String> iterator = IterableExtensions.map(list, functionForRemove).iterator();
		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, Iterable<String>> function = new Functions.Function1<String, Iterable<String>>() {
			@Override
			public Iterable<String> apply(String p) {
				return newArrayList("Hello", p);
			}
		};
		assertEquals(newArrayList("Hello", "foo", "Hello", "bar"), newArrayList(IterableExtensions.flatMap(list, function)));
	}
	
	@Test public void testContains() {
		ArrayList<String> list = newArrayList("element1", "element2", "element3", null);
		
		assertTrue(IterableExtensions.contains(list, "element3"));
		assertTrue(IterableExtensions.contains(list, new String("element3")));
		assertTrue(IterableExtensions.contains(list, null));
		
		assertFalse(IterableExtensions.contains(list, "element4"));
		assertFalse(IterableExtensions.contains(list, new String("element4")));
	}
	
	private static class TestableCollection<T> extends ForwardingCollection<T> {

		private Collection<T> original;
		boolean containsWasCalled;
		Object containsParameter;
		
		public TestableCollection(Collection<T> original) {
			super();
			this.original = original;
		}

		@Override
		protected Collection<T> delegate() {
			return original;
		}
		
		@Override
		public boolean contains(Object object) {
			containsWasCalled = true;
			containsParameter = object;
			return super.contains(object);
		}
	}
	
	@Test public void testContainsOnCollection() {
		//GIVEN a collection, declared as an iterable
		TestableCollection<String> collection = new TestableCollection<String>(newHashSet("element1", "element2", "element3"));
		
		//WHEN we call the contains method via the IterableExtensions
		IterableExtensions.contains(collection, "element1");
		
		//THEN we expect that the collection's native contains method was used
		assertTrue("IterableExtensions.contains didn't use the collection's native contains method",
					collection.containsWasCalled);
		assertEquals("element1", collection.containsParameter);
	}
}
