/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.collection.suite;

import java.util.function.Function;
import javax.annotation.Resource;
import net.ranides.assira.collection.IntCollection;
import net.ranides.assira.collection.lists.IntArrayList;
import net.ranides.assira.collection.lists.IntList;
import net.ranides.assira.collection.lists.NativeArrayList;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.test.TCollection;
import net.ranides.assira.junit.TestContract;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class IntCollectionTester {
    
    @Resource(name = "collection!")
    private TCollection<?> $var;
    
    @TestContract
    public void basicAdd(IntCollection target) {
		target.add($var.item(0).valueInt());
        assertEquals(1, target.size());
		
        target.add($var.item(1).valueInt());
        assertEquals(2, target.size());
        
		target.add($var.item(2).valueInt());
        assertEquals(3, target.size());
    }
    
    @TestContract
    public void basicAddContains(IntCollection target) {
		target.add($var.item(0).valueInt());
        assertEquals(1, target.size());
		
        target.add($var.item(1).valueInt());
        assertEquals(2, target.size());
        
		target.add($var.item(2).valueInt());
        assertEquals(3, target.size());
        
        assertTrue( target.contains($var.item(0).valueInt()));
        assertTrue( target.contains($var.item(1).valueInt()));
        assertTrue( target.contains($var.item(2).valueInt()));
        assertFalse( target.contains($var.item(3).valueInt()));
    }
    
    @TestContract
    public void basicContains(Function<int[], IntCollection> f) {
        IntCollection target = f.apply(new int[]{1,2,3,4,5});
		
        assertTrue( target.contains($var.item(1).valueInt()));
        assertFalse( target.contains($var.item(6).valueInt()));
        
        assertTrue( target.containsAll($list(1,2,3)) );
        assertTrue( target.containsAll($list(3,4,5)) );
        assertTrue( target.containsAll($list(1,2,3,4,5)) );
        
        assertFalse( target.containsAll($list(6)) );
        assertFalse( target.containsAll($list(1,2,6)) );
        assertFalse( target.containsAll($list(1,6,2,3)) );
    }
    
    @TestContract
    public void basicRemove(Function<int[], IntCollection> f) {
        IntCollection target = f.apply(new int[]{1,2,3,4,5});
        assertContentEquals($list(1,2,3,4,5), target);

        assertTrue(target.remove($var.item(2).valueInt()));
        assertContentEquals($list(1,3,4,5), target);
        
        assertTrue(target.remove($var.item(4).valueInt()));
        assertContentEquals($list(1,3,5), target);
        
        assertFalse(target.remove($var.item(7).valueInt()));
        assertContentEquals($list(1,3,5), target);
        
        assertFalse(target.removeAll($list(10,11)));
        assertContentEquals($list(1,3,5), target);
        
        assertTrue(target.removeAll($list(1,3,5,9)));
        assertEmpty(target);
    }
    
    @TestContract
    public void basicRetainAll(Function<int[], IntCollection> f) {
        IntCollection target = f.apply(new int[]{1,2,3,4,5});
        assertContentEquals($list(1,2,3,4,5), target);

        assertFalse(target.retainAll($list(1,2,3,4,5,9)));
        assertContentEquals($list(1,2,3,4,5), target);
        
        assertTrue(target.retainAll($list(1,3,10)));
        assertContentEquals($list(1,3), target);

        assertTrue(target.retainAll($list(12)));
        assertEmpty(target);
    }
    
    @TestContract
    public void basicToArray(Function<int[], IntCollection> f) {
        IntCollection target = f.apply(new int[]{1,2,3,4,5});
        int[] t = target.toIntArray();
        int[] e = $var.list(1,2,3,4,5).valuesInt();
        assertArrayContentEquals(e, t);
    }
    
    @TestContract
    public void basicToArrayG(Function<int[], IntCollection> f) {
        IntCollection target = f.apply(new int[]{1,2,3,4,5});
        int[] e = $var.list(1,2,3,4,5).valuesInt();
        
        assertArrayContentEquals(e, target.toArray(new int[0]));
        assertArrayContentEquals(e, target.toArray(new int[3]));
        
        IntList list = $list(1,2,3,4,5);
        list.add(0);
        list.add(0);
        list.add(0);
        int[] e8 = list.toIntArray();
        assertArrayContentEquals(e8, target.toArray(new int[8]));
    }
    
    private IntList $list(int... values) {
        return $var.list(values).intoInt(new IntArrayList());
    }
    
    private static <Q> void assertContentEquals(IntCollection a, IntCollection b) {
        assertTrue("assertContentEquals", a.containsAll(b) && b.containsAll(a));
    }
    
    private static void assertArrayContentEquals(int[] a, int[] b) {
        IntList alist = NativeArrayList.wrap(a);
        IntList blist = NativeArrayList.wrap(b);
        assertTrue("assertContentEquals", alist.containsAll(blist) && blist.containsAll(alist));
    }
    
    private void assertEmpty(IntCollection target) {
        assertEquals(0, target.size());
        assertTrue(target.isEmpty());
        assertContentEquals($list(), target);
    }

}
