package migl.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import java.util.HashMap;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

public class ConsListOwnTest {
	
	private ConsList<Integer> list;

	@Before
	public void init() {
		list = ConsListFactory.nil();
	}
	
	@Test
	public void testConsListImplEquals() {
		ConsList<Integer> list2 = ConsListFactory.asList(8, 88);
		ConsList<Integer> list3 = ConsListFactory.asList(88, 8);
		list = list.prepend(88).prepend(8);
		assertTrue(list.equals(list));
		assertTrue(list.equals(list2));
		assertFalse(list.equals(list3));
		assertFalse(list.equals(null));
		assertTrue(list.equals(ConsListFactory.asList(8, 88)));
		assertTrue(list.equals(ConsListFactory.singleton(88).prepend(8)));
		assertFalse(list.equals(ConsListFactory.singleton(88).prepend(888)));
		assertEquals(list.hashCode(), list2.hashCode());
		assertNotEquals(list.hashCode(), list3.hashCode());
	}
	
	@Test
	public void testConsListImplHashCode() {
		ConsList<Integer> list2 = ConsListFactory.asList(8, 888);
		ConsList<Integer> list3 = ConsListFactory.asList(88, 8);
		list = list.prepend(88).prepend(8);
		Map<ConsList<Integer>, String> map = new HashMap<>();
		map.put(list, "L1");
		map.put(list2, "L2");
		map.put(list3, "L3");
		assertEquals("L1", map.get(list));
		assertEquals("L2", map.get(list2));
		assertEquals("L3", map.get(list3));
	}

	@Test
	public void testAsListEmpty() {
		ConsList<Integer> list2 = ConsListFactory.asList();
		assertEquals(list, list2);
	}
	
	@Test
	public void testAsListSingleton() {
		ConsList<Integer> list1 = ConsListFactory.singleton(8);
		ConsList<Integer> list2 = ConsListFactory.asList(8);
		assertEquals(list1, list2);
	}
	
	@Test
	public void testConsEmptyListMap() {
		ConsList<String> list2 = ConsListFactory.nil();
		assertEquals(list2, list.map(p -> Integer.valueOf(p)));
	}
	
	@Test
	public void testIsEmpty() {
		assertTrue(list.isEmpty());
		assertEquals(list.size(), 0);
		list = list.prepend(8);
		assertFalse(list.isEmpty());
		assertNotEquals(list.size(), 0);
	}
	
	@Test(expected = IllegalArgumentException.class)
    public void testCreateEmptyConsListImpl() {
        list = new ConsListImpl<Integer>(null, null);
    }
	
	@Test
	public void testListWithNull() {
		list = list.prepend(null);
		assertEquals(1, list.size());
		assertEquals("(null)", list.toString());
	}
	
}
