/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.rng.examples.stress;

import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.core.source64.RandomLongSource;
import org.apache.commons.rng.simple.RandomSource;

import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Specification for the "stress" command.
 *
 * <p>This command loads a list of random generators and tests each generator by
 * piping the values returned by its {@link UniformRandomProvider#nextInt()}
 * method to a program that reads {@code int} values from its standard input and
 * writes an analysis report to standard output.</p>
 */
@Command(name = "stress",
         description = {"Run repeat trials of random data generators using a provided test application.",
                        "Data is transferred to the application sub-process via standard input."})
class StressTestCommand implements Callable<Void> {
    /** 1000. Any value below this can be exactly represented to 3 significant figures. */
    private static final int ONE_THOUSAND = 1000;

    /** The standard options. */
    @Mixin
    private StandardOptions reusableOptions;

    /** The executable. */
    @Parameters(index = "0",
                description = "The stress test executable.")
    private File executable;

    /** The executable arguments. */
    @Parameters(index = "1..*",
                description = "The arguments to pass to the executable.",
                paramLabel = "<argument>")
    private List<String> executableArguments = new ArrayList<>();

    /** The file output prefix. */
    @Option(names = {"--prefix"},
            description = "Results file prefix (default: ${DEFAULT-VALUE}).")
    private File fileOutputPrefix = new File("test_");

    /** The stop file. */
    @Option(names = {"--stop-file"},
            description = {"Stop file (default: <Results file prefix>.stop).",
                           "When created it will prevent new tasks from starting " +
                           "but running tasks will complete."})
    private File stopFile;

    /** The output mode for existing files. */
    @Option(names = {"-o", "--output-mode"},
            description = {"Output mode for existing files (default: ${DEFAULT-VALUE}).",
                           "Valid values: ${COMPLETION-CANDIDATES}."})
    private StressTestCommand.OutputMode outputMode = OutputMode.ERROR;

    /** The list of random generators. */
    @Option(names = {"-l", "--list"},
            description = {"List of random generators.",
                           "The default list is all known generators."},
            paramLabel = "<genList>")
    private File generatorsListFile;

    /** The number of trials to put in the template list of random generators. */
    @Option(names = {"-t", "--trials"},
            description = {"The number of trials for each random generator.",
                           "Used only for the default list (default: ${DEFAULT-VALUE})."})
    private int trials = 1;

    /** The trial offset. */
    @Option(names = {"--trial-offset"},
            description = {"Offset to add to the trial number for output files (default: ${DEFAULT-VALUE}).",
                           "Use for parallel tests with the same output prefix."})
    private int trialOffset;

    /** The number of available processors. */
    @Option(names = {"-p", "--processors"},
            description = {"Number of available processors (default: ${DEFAULT-VALUE}).",
                           "Number of concurrent tasks = ceil(processors / threadsPerTask)",
                           "threadsPerTask = applicationThreads + (ignoreJavaThread ? 0 : 1)"})
    private int processors = Math.max(1, Runtime.getRuntime().availableProcessors());

    /** The number of threads to use for each test task. */
    @Option(names = {"--ignore-java-thread"},
            description = {"Ignore the java RNG thread when computing concurrent tasks."})
    private boolean ignoreJavaThread;

    /** The number of threads to use for each testing application. */
    @Option(names = {"--threads"},
            description = {"Number of threads to use for each application (default: ${DEFAULT-VALUE}).",
                           "Total threads per task includes an optional java thread."})
    private int applicationThreads = 1;

    /** The size of the byte buffer for the binary data. */
    @Option(names = {"--buffer-size"},
            description = {"Byte-buffer size for the transferred data (default: ${DEFAULT-VALUE})."})
    private int bufferSize = 8192;

    /** The output byte order of the binary data. */
    @Option(names = {"-b", "--byte-order"},
            description = {"Byte-order of the transferred data (default: ${DEFAULT-VALUE}).",
                           "Valid values: BIG_ENDIAN, LITTLE_ENDIAN."})
    private ByteOrder byteOrder = ByteOrder.nativeOrder();

    /** Flag to indicate the output should be bit-reversed. */
    @Option(names = {"-r", "--reverse-bits"},
            description = {"Reverse the bits in the data (default: ${DEFAULT-VALUE}).",
                           "Note: Generators may fail tests for a reverse sequence " +
                           "when passing using the standard sequence."})
    private boolean reverseBits;

    /** Flag to use the upper 32-bits from the 64-bit long output. */
    @Option(names = {"--high-bits"},
            description = {"Use the upper 32-bits from the 64-bit long output.",
                           "Takes precedent over --low-bits."})
    private boolean longHighBits;

    /** Flag to use the lower 32-bits from the 64-bit long output. */
    @Option(names = {"--low-bits"},
            description = {"Use the lower 32-bits from the 64-bit long output."})
    private boolean longLowBits;

    /** Flag to use 64-bit long output. */
    @Option(names = {"--raw64"},
            description = {"Use 64-bit output (default is 32-bit).",
                           "This requires a 64-bit testing application and native 64-bit generators.",
                           "In 32-bit mode the output uses the upper then lower bits of 64-bit " +
                           "generators sequentially, each appropriately byte reversed for the platform."})
    private boolean raw64;

    /** The random seed as a byte[]. */
    @Option(names = {"-x", "--hex-seed"},
            description = {"The hex-encoded random seed.",
                           "Seed conversion for multi-byte primitives use little-endian format.",
                           "Use to repeat tests. Not recommended for batch testing."})
    private String byteSeed;

    /**
     * Flag to indicate the output should be combined with a hashcode from a new object.
     * This is a method previously used in the
     * {@link org.apache.commons.rng.simple.internal.SeedFactory SeedFactory}.
     *
     * @see System#identityHashCode(Object)
     */
    @Option(names = {"--hashcode"},
            description = {"Combine the bits with a hashcode (default: ${DEFAULT-VALUE}).",
                           "System.identityHashCode(new Object()) ^ rng.nextInt()."})
    private boolean xorHashCode;

    /**
     * Flag to indicate the output should be combined with output from ThreadLocalRandom.
     */
    @Option(names = {"--local-random"},
            description = {"Combine the bits with ThreadLocalRandom (default: ${DEFAULT-VALUE}).",
                           "ThreadLocalRandom.current().nextInt() ^ rng.nextInt()."})
    private boolean xorThreadLocalRandom;

    /**
     * Optional second generator to be combined with the primary generator.
     */
    @Option(names = {"--xor-rng"},
            description = {"Combine the bits with a second generator.",
                           "xorRng.nextInt() ^ rng.nextInt().",
                           "Valid values: Any known RandomSource enum value."})
    private RandomSource xorRandomSource;

    /** The flag to indicate a dry run. */
    @Option(names = {"--dry-run"},
            description = "Perform a dry run where the generators and output files are created " +
                          "but the stress test is not executed.")
    private boolean dryRun;

    /** The locl to hold when checking the stop file. */
    private ReentrantLock stopFileLock = new ReentrantLock(false);
    /** The stop file exists flag. This should be read/updated when holding the lock. */
    private boolean stopFileExists;
    /**
     * The timestamp when the stop file was last checked.
     * This should be read/updated when holding the lock.
     */
    private long stopFileTimestamp;

    /**
     * The output mode for existing files.
     */
    enum OutputMode {
        /** Error if the files exists. */
        ERROR,
        /** Skip existing files. */
        SKIP,
        /** Append to existing files. */
        APPEND,
        /** Overwrite existing files. */
        OVERWRITE
    }

    /**
     * Validates the run command arguments, creates the list of generators and runs the
     * stress test tasks.
     */
    @Override
    public Void call() {
        LogUtils.setLogLevel(reusableOptions.logLevel);
        ProcessUtils.checkExecutable(executable);
        ProcessUtils.checkOutputDirectory(fileOutputPrefix);
        checkStopFileDoesNotExist();
        final Iterable<StressTestData> stressTestData = createStressTestData();
        printStressTestData(stressTestData);
        runStressTest(stressTestData);
        return null;
    }

    /**
     * Initialise the stop file to a default unless specified by the user, then check it
     * does not currently exist.
     *
     * @throws ApplicationException If the stop file exists
     */
    private void checkStopFileDoesNotExist() {
        if (stopFile == null) {
            stopFile = new File(fileOutputPrefix + ".stop");
        }
        if (stopFile.exists()) {
            throw new ApplicationException("Stop file exists: " + stopFile);
        }
    }

    /**
     * Check if the stop file exists.
     *
     * <p>This method is thread-safe. It will log a message if the file exists one time only.
     *
     * @return true if the stop file exists
     */
    private boolean isStopFileExists() {
        stopFileLock.lock();
        try {
            if (!stopFileExists) {
                // This should hit the filesystem each time it is called.
                // To prevent this happening a lot when all the first set of tasks run use
                // a timestamp to limit the check to 1 time each interval.
                final long timestamp = System.currentTimeMillis();
                if (timestamp > stopFileTimestamp) {
                    checkStopFile(timestamp);
                }
            }
            return stopFileExists;
        } finally {
            stopFileLock.unlock();
        }
    }

    /**
     * Check if the stop file exists. Update the timestamp for the next check. If the stop file
     * does exists then log a message.
     *
     * @param timestamp Timestamp of the last check.
     */
    private void checkStopFile(final long timestamp) {
        stopFileTimestamp = timestamp + TimeUnit.SECONDS.toMillis(2);
        stopFileExists = stopFile.exists();
        if (stopFileExists) {
            LogUtils.info("Stop file detected: %s", stopFile);
            LogUtils.info("No further tasks will start");
        }
    }

    /**
     * Creates the test data.
     *
     * <p>If the input file is null then a default list is created.
     *
     * @return the stress test data
     * @throws ApplicationException if an error occurred during the file read.
     */
    private Iterable<StressTestData> createStressTestData() {
        if (generatorsListFile == null) {
            return new StressTestDataList("", trials);
        }
        // Read data into a list
        try (BufferedReader reader = Files.newBufferedReader(generatorsListFile.toPath())) {
            return ListCommand.readStressTestData(reader);
        } catch (final IOException ex) {
            throw new ApplicationException("Failed to read generators list: " + generatorsListFile, ex);
        }
    }

    /**
     * Prints the stress test data if the verbosity allows. This is used to debug the list
     * of generators to be tested.
     *
     * @param stressTestData List of generators to be tested.
     */
    private static void printStressTestData(Iterable<StressTestData> stressTestData) {
        if (!LogUtils.isLoggable(LogUtils.LogLevel.DEBUG)) {
            return;
        }
        try {
            final StringBuilder sb = new StringBuilder("Testing generators").append(System.lineSeparator());
            ListCommand.writeStressTestData(sb, stressTestData);
            LogUtils.debug(sb.toString());
        } catch (final IOException ex) {
            throw new ApplicationException("Failed to show list of generators", ex);
        }
    }

    /**
     * Creates the tasks and starts the processes.
     *
     * @param stressTestData List of generators to be tested.
     */
    private void runStressTest(Iterable<StressTestData> stressTestData) {
        final List<String> command = ProcessUtils.buildSubProcessCommand(executable, executableArguments);

        LogUtils.info("Set-up stress test ...");

        // Check existing output files before starting the tasks.
        final String basePath = fileOutputPrefix.getAbsolutePath();
        checkExistingOutputFiles(basePath, stressTestData);

        final int parallelTasks = getParallelTasks();

        final ProgressTracker progressTracker = new ProgressTracker(parallelTasks);
        final List<Runnable> tasks = createTasks(command, basePath, stressTestData, progressTracker);

        // Run tasks with parallel execution.
        final ExecutorService service = Executors.newFixedThreadPool(parallelTasks);

        LogUtils.info("Running stress test ...");
        LogUtils.info("Shutdown by creating stop file: %s",  stopFile);
        progressTracker.setTotal(tasks.size());
        final List<Future<?>> taskList = submitTasks(service, tasks);

        // Wait for completion (ignoring return value).
        try {
            for (final Future<?> f : taskList) {
                try {
                    f.get();
                } catch (final ExecutionException ex) {
                    // Log the error. Do not re-throw as other tasks may be processing that
                    // can still complete successfully.
                    LogUtils.error(ex.getCause(), ex.getMessage());
                }
            }
        } catch (final InterruptedException ex) {
            // Restore interrupted state...
            Thread.currentThread().interrupt();
            throw new ApplicationException("Unexpected interruption: " + ex.getMessage(), ex);
        } finally {
            // Terminate all threads.
            service.shutdown();
        }

        LogUtils.info("Finished stress test");
    }

    /**
     * Check for existing output files.
     *
     * @param basePath The base path to the output results files.
     * @param stressTestData List of generators to be tested.
     * @throws ApplicationException If an output file exists and the output mode is error
     */
    private void checkExistingOutputFiles(String basePath,
                                          Iterable<StressTestData> stressTestData) {
        if (outputMode == StressTestCommand.OutputMode.ERROR) {
            for (final StressTestData testData : stressTestData) {
                for (int trial = 1; trial <= testData.getTrials(); trial++) {
                    // Create the output file
                    final File output = createOutputFile(basePath, testData, trial);
                    if (output.exists()) {
                        throw new ApplicationException(createExistingFileMessage(output));
                    }
                }
            }
        }
    }

    /**
     * Creates the named output file.
     *
     * <p>Note: The trial will be combined with the trial offset to create the file name.
     *
     * @param basePath The base path to the output results files.
     * @param testData The test data.
     * @param trial The trial.
     * @return the file
     */
    private File createOutputFile(String basePath,
                                  StressTestData testData,
                                  int trial) {
        return new File(String.format("%s%s_%d", basePath, testData.getId(), trial + trialOffset));
    }

    /**
     * Creates the existing file message.
     *
     * @param output The output file.
     * @return the message
     */
    private static String createExistingFileMessage(File output) {
        return "Existing output file: " + output;
    }

    /**
     * Gets the number of parallel tasks. This uses the number of available processors and
     * the number of threads to use per task.
     *
     * <pre>
     * threadsPerTask = applicationThreads + (ignoreJavaThread ? 0 : 1)
     * parallelTasks = ceil(processors / threadsPerTask)
     * </pre>
     *
     * @return the parallel tasks
     */
    private int getParallelTasks() {
        // Avoid zeros in the fraction numberator and denominator
        final int availableProcessors = Math.max(1, processors);
        final int threadsPerTask = Math.max(1, applicationThreads + (ignoreJavaThread ? 0 : 1));
        final int parallelTasks = (int) Math.ceil((double) availableProcessors / threadsPerTask);
        LogUtils.debug("Parallel tasks = %d (%d / %d)",
            parallelTasks, availableProcessors, threadsPerTask);
        return parallelTasks;
    }

    /**
     * Create the tasks for the test data. The output file for the sub-process will be
     * constructed using the base path, the test identifier and the trial number.
     *
     * @param command The command for the test application.
     * @param basePath The base path to the output results files.
     * @param stressTestData List of generators to be tested.
     * @param progressTracker Progress tracker.
     * @return the list of tasks
     */
    private List<Runnable> createTasks(List<String> command,
                                       String basePath,
                                       Iterable<StressTestData> stressTestData,
                                       ProgressTracker progressTracker) {
        final List<Runnable> tasks = new ArrayList<>();
        for (final StressTestData testData : stressTestData) {
            for (int trial = 1; trial <= testData.getTrials(); trial++) {
                // Create the output file
                final File output = createOutputFile(basePath, testData, trial);
                if (output.exists()) {
                    // In case the file was created since the last check
                    if (outputMode == StressTestCommand.OutputMode.ERROR) {
                        throw new ApplicationException(createExistingFileMessage(output));
                    }
                    // Log the decision
                    LogUtils.info("%s existing output file: %s", outputMode, output);
                    if (outputMode == StressTestCommand.OutputMode.SKIP) {
                        continue;
                    }
                }
                // Create the generator. Explicitly create a seed so it can be recorded.
                final byte[] seed = createSeed(testData.getRandomSource());
                UniformRandomProvider rng = testData.createRNG(seed);

                // Upper or lower bits from 64-bit generators must be created first.
                // This will throw if not a 64-bit generator.
                if (longHighBits) {
                    rng = RNGUtils.createLongUpperBitsIntProvider(rng);
                } else if (longLowBits) {
                    rng = RNGUtils.createLongLowerBitsIntProvider(rng);
                }

                // Combination generators. Mainly used for testing.
                // These operations maintain the native output type (int/long).
                if (xorHashCode) {
                    rng = RNGUtils.createHashCodeProvider(rng);
                }
                if (xorThreadLocalRandom) {
                    rng = RNGUtils.createThreadLocalRandomProvider(rng);
                }
                if (xorRandomSource != null) {
                    rng = RNGUtils.createXorProvider(
                            RandomSource.create(xorRandomSource),
                            rng);
                }
                if (reverseBits) {
                    rng = RNGUtils.createReverseBitsProvider(rng);
                }

                // -------
                // Note: Manipulation of the byte order for the platform is done during output.
                // -------

                // Run the test
                final Runnable r = new StressTestTask(testData.getRandomSource(), rng, seed,
                                                      output, command, this, progressTracker);
                tasks.add(r);
            }
        }
        return tasks;
    }

    /**
     * Creates the seed. This will call {@link RandomSource#createSeed()} unless a hex seed has
     * been explicitly specified on the command line.
     *
     * @param randomSource Random source.
     * @return the seed
     */
    private byte[] createSeed(RandomSource randomSource) {
        if (byteSeed != null) {
            try {
                return Hex.decodeHex(byteSeed);
            } catch (IllegalArgumentException ex) {
                throw new ApplicationException("Invalid hex seed: " + ex.getMessage(), ex);
            }
        }
        return randomSource.createSeed();
    }

    /**
     * Submit the tasks to the executor service.
     *
     * @param service The executor service.
     * @param tasks The list of tasks.
     * @return the list of submitted tasks
     */
    private static List<Future<?>> submitTasks(ExecutorService service,
                                               List<Runnable> tasks) {
        final List<Future<?>> taskList = new ArrayList<>(tasks.size());
        tasks.forEach(r -> taskList.add(service.submit(r)));
        return taskList;
    }

    /**
     * Class for reporting total progress of tasks to the console.
     *
     * <p>This stores the start and end time of tasks to allow it to estimate the time remaining
     * for all the tests.
     */
    static class ProgressTracker {
        /** The interval at which to report progress (in milliseconds). */
        private static final long PROGRESS_INTERVAL = 500;

        /** The total. */
        private int total;
        /** The level of parallelisation. */
        private final int parallelTasks;
        /** The task id. */
        private int taskId;
        /** The start time of tasks (in milliseconds from the epoch). */
        private long[] startTimes;
        /** The durations of all completed tasks (in milliseconds). This is sorted. */
        private long[] sortedDurations;
        /** The number of completed tasks. */
        private int completed;
        /** The timestamp of the next progress report. */
        private long nextReportTimestamp;

        /**
         * Create a new instance. The total number of tasks must be initialized before use.
         *
         * @param parallelTasks The number of parallel tasks.
         */
        ProgressTracker(int parallelTasks) {
            this.parallelTasks = parallelTasks;
        }

        /**
         * Sets the total number of tasks to track.
         *
         * @param total The total tasks.
         */
        void setTotal(int total) {
            this.total = total;
            startTimes = new long[total];
            sortedDurations = new long[total];
        }

        /**
         * Submit a task for progress tracking. The task start time is recorded and the
         * task is allocated an identifier.
         *
         * @return the task Id
         */
        int submitTask() {
            int id;
            synchronized (this) {
                final long current = System.currentTimeMillis();
                id = taskId++;
                startTimes[id] = current;
                reportProgress(current);
            }
            return id;
        }

        /**
         * Signal that a task has completed. The task duration will be returned.
         *
         * @param id Task Id.
         * @return the task time in milliseconds
         */
        long endTask(int id) {
            long duration;
            synchronized (this) {
                final long current = System.currentTimeMillis();
                duration = current - startTimes[id];
                sortedDurations[completed++] = duration;
                reportProgress(current);
            }
            return duration;
        }

        /**
         * Report the progress. This uses the current state and should be done within a
         * synchronized block.
         *
         * @param current Current time (in milliseconds).
         */
        private void reportProgress(long current) {
            // Determine the current state of tasks
            final int pending = total - taskId;
            final int running = taskId - completed;

            // Report progress in the following conditions:
            // - All tasks have completed (i.e. the end); or
            // - The current timestamp is above the next reporting time and either:
            // -- The number of running tasks is equal to the level of parallel tasks
            //    (i.e. the system is running at capacity, so not the end of a task but the start
            //    of a new one)
            // -- There are no pending tasks (i.e. the final submission or the end of a final task)
            if (completed >= total ||
                (current >= nextReportTimestamp && (running == parallelTasks || pending == 0))) {
                // Report
                nextReportTimestamp = current + PROGRESS_INTERVAL;
                final StringBuilder sb = createStringBuilderWithTimestamp(current, pending, running, completed);
                try (Formatter formatter = new Formatter(sb)) {
                    formatter.format(" (%.2f%%)", 100.0 * completed / total);
                    appendRemaining(sb, current, pending, running);
                    LogUtils.info(sb.toString());
                }
            }
        }

        /**
         * Creates the string builder for the progress message with a timestamp prefix.
         *
         * <pre>
         * [HH:mm:ss] Pending [pending]. Running [running]. Completed [completed]
         * </pre>
         *
         * @param current Current time (in milliseconds)
         * @param pending Pending tasks.
         * @param running Running tasks.
         * @param completed Completed tasks.
         * @return the string builder
         */
        private static StringBuilder createStringBuilderWithTimestamp(long current,
            int pending, int running, int completed) {
            final StringBuilder sb = new StringBuilder(80);
            // Use local time to adjust for timezone
            final LocalDateTime time = LocalDateTime.ofInstant(
                Instant.ofEpochMilli(current), ZoneId.systemDefault());
            sb.append('[');
            append00(sb, time.getHour()).append(':');
            append00(sb, time.getMinute()).append(':');
            append00(sb, time.getSecond());
            return sb.append("] Pending ").append(pending)
                     .append(". Running ").append(running)
                     .append(". Completed ").append(completed);
        }

        /**
         * Compute an estimate of the time remaining and append to the progress. Updates
         * the estimated time of arrival (ETA).
         *
         * @param sb String Builder.
         * @param current Current time (in milliseconds)
         * @param pending Pending tasks.
         * @param running Running tasks.
         * @return the string builder
         */
        private StringBuilder appendRemaining(StringBuilder sb, long current, int pending, int running) {
            final long millis = getRemainingTime(current, pending, running);
            if (millis == 0) {
                // Unknown.
                return sb;
            }

            // HH:mm:ss format
            sb.append(". Remaining = ");
            hms(sb, millis);
            return sb;
        }

        /**
         * Gets the remaining time (in milliseconds).
         *
         * @param current Current time (in milliseconds)
         * @param pending Pending tasks.
         * @param running Running tasks.
         * @return the remaining time
         */
        private long getRemainingTime(long current, int pending, int running) {
            final long taskTime = getEstimatedTaskTime();
            if (taskTime == 0) {
                // No estimate possible
                return 0;
            }

            // The start times are sorted. This method assumes the most recent start times
            // are still running tasks.
            // If this is wrong (more recently submitted tasks finished early) the result
            // is the estimate is too high. This could be corrected by storing the tasks
            // that have finished and finding the times of only running tasks.

            // The remaining time is:
            //   The time for all running tasks to finish
            // + The time for pending tasks to run

            // The id of the most recently submitted task.
            // Guard with a minimum index of zero to get a valid index.
            final int id = Math.max(0, taskId - 1);

            // If there is a running task assume the youngest task is still running
            // and estimate the time left.
            long millis = (running == 0) ? 0 : getTimeRemaining(taskTime, current, startTimes[id]);

            // If additional tasks must also be submitted then the time must include
            // the estimated time for running tasks to finish before new submissions
            // in the batch can be made.
            //                   now
            // s1 --------------->|
            //      s2 -----------|-------->
            //          s3 -------|------------>
            //                    s4 -------------->
            //

            // Assume parallel batch execution.
            // E.g. 3 additional tasks with parallelisation 4 is 0 batches
            int batches = pending / parallelTasks;
            millis += batches * taskTime;

            // Compute the expected end time of the final batch based on it starting when
            // a currently running task ends.
            // E.g. 3 remaining tasks requires the end time of the 3rd oldest running task.
            int remainder = pending % parallelTasks;
            if (remainder != 0) {
                // Guard with a minimum index of zero to get a valid index.
                final int nthOldest = Math.max(0, id - parallelTasks + remainder);
                millis += getTimeRemaining(taskTime, current, startTimes[nthOldest]);
            }

            return millis;
        }

        /**
         * Gets the estimated task time.
         *
         * @return the estimated task time
         */
        private long getEstimatedTaskTime() {
            Arrays.sort(sortedDurations, 0, completed);

            // Return median of small lists. If no tasks have finished this returns zero.
            // as the durations is zero initialized.
            if (completed < 4) {
                return sortedDurations[completed / 2];
            }

            // Dieharder and BigCrush run in approximately constant time.
            // Speed varies with the speed of the RNG by about 2-fold, and
            // for Dieharder it may repeat suspicious tests.
            // PractRand may fail very fast for bad generators which skews
            // using the mean or even the median. So look at the longest
            // running tests.

            // Find long running tests (>50% of the max run-time)
            int upper = completed - 1;
            final long halfMax = sortedDurations[upper] / 2;
            // Binary search for the approximate cut-off
            int lower = 0;
            while (lower + 1 < upper) {
                int mid = (lower + upper) >>> 1;
                if (sortedDurations[mid] < halfMax) {
                    lower = mid;
                } else {
                    upper = mid;
                }
            }
            // Use the median of all tasks within approximately 50% of the max.
            return sortedDurations[(upper + completed - 1) / 2];
        }

        /**
         * Gets the time remaining for the task.
         *
         * @param taskTime Estimated task time.
         * @param current Current time.
         * @param startTime Start time.
         * @return the time remaining
         */
        private static long getTimeRemaining(long taskTime, long current, long startTime) {
            final long endTime = startTime + taskTime;
            // Ensure the time is positive in the case where the estimate is too low.
            return Math.max(0, endTime - current);
        }

        /**
         * Append the milliseconds using {@code HH::mm:ss} format.
         *
         * @param sb String Builder.
         * @param millis Milliseconds.
         * @return the string builder
         */
        static StringBuilder hms(StringBuilder sb, final long millis) {
            final long hours = TimeUnit.MILLISECONDS.toHours(millis);
            long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
            long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
            // Truncate to interval [0,59]
            seconds -= TimeUnit.MINUTES.toSeconds(minutes);
            minutes -= TimeUnit.HOURS.toMinutes(hours);

            append00(sb, hours).append(':');
            append00(sb, minutes).append(':');
            return append00(sb, seconds);
        }

        /**
         * Append the ticks to the string builder in the format {@code %02d}.
         *
         * @param sb String Builder.
         * @param ticks Ticks.
         * @return the string builder
         */
        static StringBuilder append00(StringBuilder sb, long ticks) {
            if (ticks == 0) {
                sb.append("00");
            } else {
                if (ticks < 10) {
                    sb.append('0');
                }
                sb.append(ticks);
            }
            return sb;
        }
    }

    /**
     * Pipes random numbers to the standard input of an analyzer executable.
     */
    private static class StressTestTask implements Runnable {
        /** Comment prefix. */
        private static final String C = "# ";
        /** New line. */
        private static final String N = System.lineSeparator();
        /** The date format. */
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        /** The SI units for bytes in increments of 10^3. */
        private static final String[] SI_UNITS = {"B", "kB", "MB", "GB", "TB", "PB", "EB"};
        /** The SI unit base for bytes (10^3). */
        private static final long SI_UNIT_BASE = 1000;

        /** The random source. */
        private final RandomSource randomSource;
        /** RNG to be tested. */
        private final UniformRandomProvider rng;
        /** The seed used to create the RNG. */
        private final byte[] seed;
        /** Output report file of the sub-process. */
        private final File output;
        /** The sub-process command to run. */
        private final List<String> command;
        /** The stress test command. */
        private final StressTestCommand cmd;
        /** The progress tracker. */
        private final ProgressTracker progressTracker;

        /** The count of bytes used by the sub-process. */
        private long bytesUsed;

        /**
         * Creates the task.
         *
         * @param randomSource The random source.
         * @param rng RNG to be tested.
         * @param seed The seed used to create the RNG.
         * @param output Output report file.
         * @param command The sub-process command to run.
         * @param cmd The run command.
         * @param progressTracker The progress tracker.
         */
        StressTestTask(RandomSource randomSource,
                       UniformRandomProvider rng,
                       byte[] seed,
                       File output,
                       List<String> command,
                       StressTestCommand cmd,
                       ProgressTracker progressTracker) {
            this.randomSource = randomSource;
            this.rng = rng;
            this.seed = seed;
            this.output = output;
            this.command = command;
            this.cmd = cmd;
            this.progressTracker = progressTracker;
        }

        /** {@inheritDoc} */
        @Override
        public void run() {
            if (cmd.isStopFileExists()) {
                // Do nothing
                return;
            }

            try {
                printHeader();

                Object exitValue;
                long millis;
                final int taskId = progressTracker.submitTask();
                if (cmd.dryRun) {
                    // Do not do anything. Ignore the runtime.
                    exitValue = "N/A";
                    progressTracker.endTask(taskId);
                    millis = 0;
                } else {
                    // Run the sub-process
                    exitValue = runSubProcess();
                    millis = progressTracker.endTask(taskId);
                }

                printFooter(millis, exitValue);

            } catch (final IOException ex) {
                throw new ApplicationException("Failed to run task: " + ex.getMessage(), ex);
            }
        }

        /**
         * Run the analyzer sub-process command.
         *
         * @return The exit value.
         * @throws IOException Signals that an I/O exception has occurred.
         */
        private Integer runSubProcess() throws IOException {
            // Start test suite.
            final ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectOutput(ProcessBuilder.Redirect.appendTo(output));
            builder.redirectErrorStream(true);
            final Process testingProcess = builder.start();

            // Use a custom data output to write the RNG.
            try (RngDataOutput sink = RNGUtils.createDataOutput(rng, cmd.raw64,
                testingProcess.getOutputStream(), cmd.bufferSize, cmd.byteOrder)) {
                for (;;) {
                    sink.write(rng);
                    bytesUsed++;
                }
            } catch (final IOException ignored) {
                // Hopefully getting here when the analyzing software terminates.
            }

            bytesUsed *= cmd.bufferSize;

            // Get the exit value.
            // Wait for up to 60 seconds.
            // If an application does not exit after this time then something is wrong.
            // Dieharder and TestU01 BigCrush exit within 1 second.
            // PractRand has been observed to take longer than 1 second. It calls std::exit(0)
            // when failing a test so the length of time may be related to freeing memory.
            return ProcessUtils.getExitValue(testingProcess, TimeUnit.SECONDS.toMillis(60));
        }

        /**
         * Prints the header.
         *
         * @throws IOException if there was a problem opening or writing to the
         * {@code output} file.
         */
        private void printHeader() throws IOException {
            final StringBuilder sb = new StringBuilder(200);
            sb.append(C).append(N)
                .append(C).append("RandomSource: ").append(randomSource.name()).append(N)
                .append(C).append("RNG: ").append(rng.toString()).append(N)
                .append(C).append("Seed: ").append(Hex.encodeHex(seed)).append(N)
                .append(C).append(N)

            // Match the output of 'java -version', e.g.
            // java version "1.8.0_131"
            // Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
            // Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
            .append(C).append("Java: ").append(System.getProperty("java.version")).append(N);
            appendNameAndVersion(sb, "Runtime", "java.runtime.name", "java.runtime.version");
            appendNameAndVersion(sb, "JVM", "java.vm.name", "java.vm.version", "java.vm.info");

            sb.append(C).append("OS: ").append(System.getProperty("os.name"))
                .append(' ').append(System.getProperty("os.version"))
                .append(' ').append(System.getProperty("os.arch")).append(N)
                .append(C).append("Native byte-order: ").append(ByteOrder.nativeOrder()).append(N)
                .append(C).append("Output byte-order: ").append(cmd.byteOrder).append(N);
            if (rng instanceof RandomLongSource) {
                sb.append(C).append("64-bit output: ").append(cmd.raw64).append(N);
            }
            sb.append(C).append(N)
                .append(C).append("Analyzer: ");
            for (final String s : command) {
                sb.append(s).append(' ');
            }
            sb.append(N)
              .append(C).append(N);

            appendDate(sb, "Start").append(C).append(N);

            write(sb, output, cmd.outputMode == StressTestCommand.OutputMode.APPEND);
        }

        /**
         * Prints the footer.
         *
         * @param millis Duration of the run (in milliseconds).
         * @param exitValue The process exit value.
         * @throws IOException if there was a problem opening or writing to the
         * {@code output} file.
         */
        private void printFooter(long millis,
                                 Object exitValue) throws IOException {
            final StringBuilder sb = new StringBuilder(200);
            sb.append(C).append(N);

            appendDate(sb, "End").append(C).append(N);

            sb.append(C).append("Exit value: ").append(exitValue).append(N)
                .append(C).append("Bytes used: ").append(bytesUsed)
                          .append(" >= 2^").append(log2(bytesUsed))
                          .append(" (").append(bytesToString(bytesUsed)).append(')').append(N)
                .append(C).append(N);

            final double duration = millis * 1e-3 / 60;
            sb.append(C).append("Test duration: ").append(duration).append(" minutes").append(N)
                .append(C).append(N);

            write(sb, output, true);
        }

        /**
         * Write the string builder to the output file.
         *
         * @param sb The string builder.
         * @param output The output file.
         * @param append Set to {@code true} to append to the file.
         * @throws IOException Signals that an I/O exception has occurred.
         */
        private static void write(StringBuilder sb,
                                  File output,
                                  boolean append) throws IOException {
            try (BufferedWriter w = append ?
                    Files.newBufferedWriter(output.toPath(), StandardOpenOption.APPEND) :
                    Files.newBufferedWriter(output.toPath())) {
                w.write(sb.toString());
            }
        }

        /**
         * Append prefix and then name and version from System properties, finished with
         * a new line. The format is:
         *
         * <pre>{@code # <prefix>: <name> (build <version>[, <info>, ...])}</pre>
         *
         * @param sb The string builder.
         * @param prefix The prefix.
         * @param nameKey The name key.
         * @param versionKey The version key.
         * @param infoKeys The additional information keys.
         * @return the StringBuilder.
         */
        private static StringBuilder appendNameAndVersion(StringBuilder sb,
                                                          String prefix,
                                                          String nameKey,
                                                          String versionKey,
                                                          String... infoKeys) {
            appendPrefix(sb, prefix)
                .append(System.getProperty(nameKey, "?"))
                .append(" (build ")
                .append(System.getProperty(versionKey, "?"));
            for (final String key : infoKeys) {
                final String value = System.getProperty(key, "");
                if (!value.isEmpty()) {
                    sb.append(", ").append(value);
                }
            }
            return sb.append(')').append(N);
        }

        /**
         * Append a comment with the current date to the {@link StringBuilder}, finished with
         * a new line. The format is:
         *
         * <pre>{@code # <prefix>: yyyy-MM-dd HH:mm:ss}</pre>
         *
         * @param sb The StringBuilder.
         * @param prefix The prefix used before the formatted date, e.g. "Start".
         * @return the StringBuilder.
         */
        private static StringBuilder appendDate(StringBuilder sb,
                                                String prefix) {
            // Use local date format. It is not thread safe.
            final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
            return appendPrefix(sb, prefix).append(dateFormat.format(new Date())).append(N);
        }

        /**
         * Append a comment with the current date to the {@link StringBuilder}.
         *
         * <pre>
         * {@code # <prefix>: yyyy-MM-dd HH:mm:ss}
         * </pre>
         *
         * @param sb The StringBuilder.
         * @param prefix The prefix used before the formatted date, e.g. "Start".
         * @return the StringBuilder.
         */
        private static StringBuilder appendPrefix(StringBuilder sb,
                                                  String prefix) {
            return sb.append(C).append(prefix).append(": ");
        }

        /**
         * Convert bytes to a human readable string. Example output:
         *
         * <pre>
         *                              SI
         *                   0:        0 B
         *                  27:       27 B
         *                 999:      999 B
         *                1000:     1.0 kB
         *                1023:     1.0 kB
         *                1024:     1.0 kB
         *                1728:     1.7 kB
         *              110592:   110.6 kB
         *             7077888:     7.1 MB
         *           452984832:   453.0 MB
         *         28991029248:    29.0 GB
         *       1855425871872:     1.9 TB
         * 9223372036854775807:     9.2 EB   (Long.MAX_VALUE)
         * </pre>
         *
         * @param bytes the bytes
         * @return the string
         * @see <a
         * href="https://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java">How
         *      to convert byte size into human readable format in java?</a>
         */
        static String bytesToString(long bytes) {
            // When using the smallest unit no decimal point is needed, because it's the exact number.
            if (bytes < ONE_THOUSAND) {
                return bytes + " " + SI_UNITS[0];
            }

            final int exponent = (int) (Math.log(bytes) / Math.log(SI_UNIT_BASE));
            final String unit = SI_UNITS[exponent];
            return String.format(Locale.US, "%.1f %s", bytes / Math.pow(SI_UNIT_BASE, exponent), unit);
        }

        /**
         * Return the log2 of a {@code long} value rounded down to a power of 2.
         *
         * @param x the value
         * @return {@code floor(log2(x))}
         */
        static int log2(long x) {
            return 63 - Long.numberOfLeadingZeros(x);
        }
    }
}
