package net.ranides.assira.collection.query.base;

import net.ranides.test.CQueryAssert;
import org.junit.Assert;
import org.junit.Test;

import net.ranides.assira.collection.lists.IntRange;
import net.ranides.assira.collection.query.CQuery;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import static org.junit.Assert.*;

public class CQArrayTest {

    @Test
    public void testLimitList() {
        Integer[] input = {7, 6, 2, 3, 4, 9, 2, 5, 1, 6, 7, 8, 4};

        CQueryAssert.assertEquals(Arrays.asList(7,6,2,3), CQuery.from().values(input).limit(4));
        CQueryAssert.assertEquals(Arrays.asList(2,3,4,9), CQuery.from().values(input).skip(2).limit(4));
        CQueryAssert.assertEquals(Arrays.asList(2,3), CQuery.from().values(input).limit(4).skip(2));

        CQueryAssert.assertEquals(Arrays.asList(2,3), CQuery.from().values(input).limit(4).slice(2,4));
        CQueryAssert.assertEquals(Arrays.asList(2,3), CQuery.from().values(input).limit(4).slice(2,6));

        List<Integer> out3 = new ArrayList<>();
        assertEquals(18, CQuery.from().values(input).skip(2).limit(4).onEach(v -> out3.add(v)).reduce(Integer::sum).intValue());
        assertEquals(Arrays.asList(2,3,4,9), out3);

        List<String> out4 = new ArrayList<>();
        assertEquals(64, CQuery.from().values(input)
            .onEach((i,v) -> out4.add(i+"#"+v))
            .reduce(Integer::sum).intValue()
        );
        assertEquals(Arrays.asList("0#7", "1#6", "2#2", "3#3", "4#4", "5#9", "6#2", "7#5", "8#1", "9#6", "10#7", "11#8", "12#4"), out4);

        List<String> out5 = new ArrayList<>();
        assertEquals(18, CQuery.from().values(input)
            .limit(4).onEach((i, v) -> out5.add(i + "#" + v))
            .reduce(Integer::sum).intValue()
        );
        assertEquals(Arrays.asList("0#7", "1#6", "2#2", "3#3"), out5);

        List<String> out6 = new ArrayList<>();
        assertEquals(18, CQuery.from().values(input)
            .onEach((i, v) -> out6.add(i + "#" + v)).limit(4)
            .reduce(Integer::sum).intValue()
        );

        assertEquals(Arrays.asList("0#7", "1#6", "2#2", "3#3"), out6);
    }

    @Test
    public void whileEach() {
        Integer[] input = {7, 6, 2, 3, 4, 9, 2, 5, 1, 6, 7, 8, 4};

        int[] out1 = {0};
        boolean all = new CQArray<>(input).whileEach(v -> {
            out1[0]++;
            return v != 1;
        });
        assertFalse(all);
        assertEquals(9, out1[0]);
    }

    @Test
    public void fetch() {
        CQArray<Integer> query = new CQArray<>(new Integer[]{1, 2, 3, 4, 5});

        Assert.assertSame(query, query.fetch());
        Assert.assertSame(query, query.prefetch());
        Assert.assertSame(query, query.cache(Paths.get("abc")));
    }

    @Test
    public void paralellEach() {
        Integer[] range = new IntRange(0, 50).toArray(new Integer[0]);
        CQueryAssert.assertOrderedParallel(new CQArray<>(range));
    }
}