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

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.StreamSupport;

public class CQArrayBenchmark {

    public static void main(String[] args) {
        Integer[] range = new IntRange(0, 1000).toArray(new Integer[0]);

        compare("CQArray", range, new CQArray<>(range));
        compare("CQArraySupplier", range, CQArraySupplier.from(() -> range));

        compare("CQList", range, new CQList<>(Arrays.asList(range)));
        compare("CQListSupplier", range, CQListSupplier.from(() -> Arrays.asList(range)));

        compare("spliterator", range, CQSpliterator.from(() -> Arrays.asList(range).spliterator()));
        compare("stream.spliterator", range, CQSpliterator.from(() -> Arrays.asList(range).stream().spliterator()));
        compare("stream.parallel.spliterator", range, CQSpliterator.from(() -> Arrays.asList(range).stream().parallel().spliterator()));
    }

    private static <T> void compare(String label, T[] range, CQuery<T> query) {
        TimeMetric tmJDK = new TimeMetric();

        StreamSupport.stream(Arrays.spliterator(range), true).forEach(v -> {
            sleep(100);
        });
        long timeJDK = tmJDK.stop();

        TimeMetric tmQuery = new TimeMetric();
        query.parallel().forEach((i,v) -> {
            sleep(100);
        });
        long timeQuery = tmQuery.stop();

        long timeDt = timeQuery - timeJDK;
        System.out.printf("%-30s Time = %8dms %8dms %8dms %8d%%%n",
            label, timeJDK, timeQuery, timeDt, 100* (timeDt) / timeQuery
        );
    }

    private static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
