package com.milaboratory.util.sorting;

import com.milaboratory.util.FormatUtils;
import com.milaboratory.util.RandomUtil;
import gnu.trove.set.hash.TLongHashSet;
import org.apache.commons.math3.random.RandomGenerator;
import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class SortingUtilTest {
    @Test
    public void test1() {
        RandomGenerator r = RandomUtil.getThreadLocalRandom();
        int n = 100000;
        int k = 5;
        int v = 217;
        List<int[]> data = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            int[] record = new int[k];
            for (int j = 0; j < k; j++)
                record[j] = r.nextInt(v);
            data.add(record);
        }
        List<Function<int[], Object>> keys = new ArrayList<>();
        for (int i = 0; i < k; i++) {
            int fi = i;
            keys.add(ints -> ints[fi]);
        }

        long beforeCollate = System.nanoTime();
        List<int[]> result = SortingUtil.hGroup(data, keys);
        System.out.println("Collation: " + FormatUtils.nanoTimeToString(System.nanoTime() - beforeCollate));
        long beforeSort = System.nanoTime();
        data.sort((o1, o2) -> {
            int c;
            for (int i = 0; i < k; i++)
                if ((c = Integer.compare(o1[i], o2[i])) != 0)
                    return c;
            return 0;
        });
        System.out.println("Sorting: " + FormatUtils.nanoTimeToString(System.nanoTime() - beforeSort));

        for (int ki = 0; ki < k; ki++) {
            TLongHashSet prefixesTransitions = new TLongHashSet();
            TLongHashSet prefixesAll = new TLongHashSet();
            long previous = -1;
            for (int[] record : result) {
                long prefix = 0;
                for (int i = 0; i < ki; i++) {
                    prefix *= v;
                    prefix += record[i];
                }
                if (previous != prefix)
                    Assert.assertTrue(prefixesTransitions.add(prefix));
                prefixesAll.add(prefix);
                previous = prefix;
            }
            System.out.println(prefixesAll.size());
            Assert.assertEquals(prefixesAll, prefixesTransitions);
        }
    }
}