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

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import net.ranides.assira.collection.mockup.TMaps;
import net.ranides.assira.collection.mockup.TPoint;
import net.ranides.assira.ContractTesters;
import net.ranides.assira.test.TComparator;
import net.ranides.assira.test.TMap;
import org.junit.Test;
import static net.ranides.assira.junit.NewAssert.*;

/**
 * 
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class AVLTreeMapTest {
    
    private final TMap<TPoint, Integer> $map = TMaps.MAP_PI;

    @Test
    public void testSuite() {
        ContractTesters.runner()
            .param("map!", $map)
            .function(new int[0], array -> $map.list(array).into(new AVLTreeMap<>($map.comparator())))
			.run();
    }

    @Test
    public void testConstruct() {
        assertNotNull( new AVLTreeMap<>() );
        assertNotNull( new AVLTreeMap<>($map.comparator()) );
    }
    
    @Test
    public void testConstructCopy() {
        TMap.TItems<TPoint, Integer> items = $map.range(180);
        
		TComparator<TPoint> cmp1 = new TComparator<>(items);
		TComparator<TPoint> cmp2 = new TComparator<>(items).uorder();
		TComparator<TPoint> cmp3 = new TComparator<>(items).hash(1,2,3,4).order(1,2,3,4,5,6,7,8,9,10,11,12);
		items.shuffle(777);
		
		AVLTreeMap<TPoint, Integer> smap1 = new AVLTreeMap<>(items.keys(), items.values(), cmp1);
		AVLTreeMap<TPoint, Integer> smap2 = new AVLTreeMap<>(items.keys(), items.values(), cmp2);
		AVLTreeMap<TPoint, Integer> smap3 = new AVLTreeMap<>(items.keys(), items.values(), cmp3);

		assertEquals(180, smap1.size());
		assertEquals(120, smap2.size());
		assertEquals(12, smap3.size());
		
		Map<TPoint, Integer> imap = items.into(new TreeMap<>(cmp1));
		
        assertEquals(180, new AVLTreeMap<>(imap).size());
        assertEquals(180, new AVLTreeMap<>((SortedMap<TPoint,Integer>)imap).size());
        
        assertEquals(180, new AVLTreeMap<>(smap1).size());
        assertEquals(120, new AVLTreeMap<>(smap2).size());
        
        assertEquals(180, new AVLTreeMap<>(items.keys(), items.values(), cmp1).size());
        assertEquals(120, new AVLTreeMap<>(items.keys(), items.values(), cmp2).size());
        assertEquals(12, new AVLTreeMap<>(items.keys(), items.values(), cmp3).size());
        
		assertEquals(180, new AVLTreeMap<>(items.keys(), items.values()).size());

        assertThrows(IllegalArgumentException.class, () -> 
            new AVLTreeMap<>($map.range(60).keys(), $map.range(40).values(), cmp1)
        );
    }
    
    @Test
    public void testMultiSet() {
        AVLTreeMultiMap<TPoint, Integer> map = new AVLTreeMultiMap<>($map.comparator());
        $map.item(2, 1).into(map);
        $map.item(3, 1).into(map);
        $map.item(6, 1).into(map);
        $map.item(6, 1).into(map);
        $map.item(6, 2).into(map);
        $map.item(7, 1).into(map);
        $map.item(7, 2).into(map);
        map.put($map.item(7, 2).key(), $map.item(7, 3).value());
        $map.item(11, 2).into(map);
        $map.item(13, 2).into(map);
        
        assertEquals(9, map.tailMap($map.item(2).key()).size());
        assertEquals(8, map.tailMap($map.item(3).key()).size());
        assertEquals(7, map.tailMap($map.item(6,1).key()).size());
        assertEquals(6, map.tailMap($map.item(6,2).key()).size());
        assertEquals(2, map.subMap($map.item(6).key(), $map.item(7).key()).size());
        assertEquals(5, map.subMap($map.item(6).key(), $map.item(11).key()).size());
        
//        System.out.printf("%s%n", map.tailMap($map.item(2).key()));
//        System.out.printf("%s%n", map.tailMap($map.item(3).key()));
//        System.out.printf("%s%n", map.tailMap($map.item(6,1).key()));
//        System.out.printf("%s%n", map.tailMap($map.item(6,2).key()));
//        System.out.printf("%s%n", map.subMap($map.item(6).key(), $map.item(7).key()));
//        System.out.printf("%s%n", map.subMap($map.item(6).key(), $map.item(11).key()));
    }

}
