package net.ranides.assira.collection.sets;

import net.ranides.test.ContractTesters;
import net.ranides.test.data.TCollection;
import net.ranides.test.data.TMaps;
import net.ranides.test.data.TPoint;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

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

public class WBTreeSetTest {

    private final TCollection<TPoint> $var = TMaps.MAP_PI.keys();

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

    @Test
    public void basic() {
        WBTreeSet<Integer> tree = new WBTreeSet<>();

        tree.add(5);
        tree.add(3);
        tree.add(1);
        tree.add(6);
        tree.add(2);
        tree.add(4);

        List<Integer> values = new ArrayList<>();
        tree.forEach(values::add);

        assertEquals(Arrays.asList(1,2,3,4,5,6), values);

        tree.remove(3);
        tree.remove(6);

        List<Integer> values2 = new ArrayList<>();
        tree.forEach(values2::add);
        assertEquals(Arrays.asList(1,2,4,5), values2);

        assertEquals(4, tree.iterator(2).next().intValue());

        assertArrayEquals(new Integer[]{1,2,4,5}, tree.toArray(new Integer[0]));
    }

    @Test
    public void sub() {
        WBTreeSet<Integer> tree = new WBTreeSet<>();

        tree.add(5);
        tree.add(3);
        tree.add(1);
        tree.add(6);
        tree.add(2);
        tree.add(4);

        assertArrayEquals(new Integer[]{1,2,3,4,5,6}, tree.toArray(new Integer[0]));

        assertArrayEquals(new Integer[]{1, 2, 3, 4, 5, 6}, tree.subSet(1, 7).toArray(new Integer[0]));
        assertArrayEquals(new Integer[]{2,3,4}, tree.subSet(2,5).toArray(new Integer[0]));
        assertArrayEquals(new Integer[]{1,2,3,4}, tree.headSet(5).toArray(new Integer[0]));
        assertArrayEquals(new Integer[]{3,4,5,6}, tree.tailSet(3).toArray(new Integer[0]));

        assertTrue(tree.subSet(1,5).contains(3));
        assertFalse(tree.subSet(1,5).contains(6));
        assertFalse(tree.subSet(1,5).contains(5));
    }

    @Test
    public void head() {
        WBTreeSet<Integer> tree = new WBTreeSet<>();

        tree.add(5);
        tree.add(3);
        tree.add(1);
        tree.add(6);
        tree.add(2);
        tree.add(4);

        assertArrayEquals(new Integer[]{}, tree.headSet(0).toArray());
        assertArrayEquals(new Integer[]{1,2}, tree.headSet(3).toArray());
    }

    @Test
    public void tail() {
        WBTreeSet<Integer> tree = new WBTreeSet<>();

        tree.add(5);
        tree.add(3);
        tree.add(1);
        tree.add(6);
        tree.add(2);
        tree.add(4);

        assertArrayEquals(new Integer[]{}, tree.tailSet(9).toArray());
        assertArrayEquals(new Integer[]{6}, tree.tailSet(6).toArray());
        assertArrayEquals(new Integer[]{3,4,5,6}, tree.tailSet(3).toArray());

        assertArrayEquals(new Integer[]{1,2,3,4,5,6}, tree.tailSet(1).toArray());
        assertArrayEquals(new Integer[]{1,2,3,4,5,6}, tree.tailSet(0).toArray());

        assertEquals(0, tree.tailSet(9).size());
        assertEquals(1, tree.tailSet(6).size());
        assertEquals(4, tree.tailSet(3).size());
    }

}