/*
 * 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.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.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Formatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Specification for the "results" command.
 *
 * <p>This command creates a summary of the results from known test applications.</p>
 *
 * <ul>
 *   <li>Dieharder
 *   <li>Test U01 (BigCrush, Crush, SmallCrush)
 * </ul>
 */
@Command(name = "results",
         description = {"Collate results from stress test applications."})
class ResultsCommand implements Callable<Void> {
    /** The pattern to identify the RandomSource in the stress test result header. */
    private static final Pattern RANDOM_SOURCE_PATTERN = Pattern.compile("^# RandomSource: (.*)");
    /** The pattern to identify the RNG in the stress test result header. */
    private static final Pattern RNG_PATTERN = Pattern.compile("^# RNG: (.*)");
    /** The pattern to identify the test exit code in the stress test result footer. */
    private static final Pattern TEST_EXIT_PATTERN = Pattern.compile("^# Exit value: (\\d+)");
    /** The pattern to identify the Dieharder test format. */
    private static final Pattern DIEHARDER_PATTERN = Pattern.compile("^# *dieharder version");
    /** The pattern to identify a Dieharder failed test result. */
    private static final Pattern DIEHARDER_FAILED_PATTERN = Pattern.compile("FAILED *$");
    /** The pattern to identify the Test U01 test format. */
    private static final Pattern TESTU01_PATTERN = Pattern.compile("^ *Version: TestU01");
    /** The pattern to identify the Test U01 summary header. */
    private static final Pattern TESTU01_SUMMARY_PATTERN = Pattern.compile("^========= Summary results of (\\S*) ");
    /** The pattern to identify the Test U01 failed test result. */
    private static final Pattern TESTU01_TEST_RESULT_PATTERN = Pattern.compile("^  ?(\\d+  .*)    ");
    /** The pattern to identify the Test U01 test starting entry. */
    private static final Pattern TESTU01_STARTING_PATTERN = Pattern.compile("^ *Starting (\\S*)");
    /** The pattern to identify the PractRand test format. */
    private static final Pattern PRACTRAND_PATTERN = Pattern.compile("PractRand version");
    /** The pattern to identify the PractRand output byte size. */
    private static final Pattern PRACTRAND_OUTPUT_SIZE_PATTERN = Pattern.compile("\\(2\\^(\\d+) bytes\\)");
    /** The pattern to identify a PractRand failed test result. */
    private static final Pattern PRACTRAND_FAILED_PATTERN = Pattern.compile("FAIL *!* *$");
    /** The name of the Dieharder sums test. */
    private static final String DIEHARDER_SUMS = "diehard_sums";
    /** The string identifying a bit-reversed generator. */
    private static final String BIT_REVERSED = "Bit-reversed";
    /** Character '\'. */
    private static final char FORWARD_SLASH = '\\';
    /** Character '/'. */
    private static final char BACK_SLASH = '\\';
    /** Character '|'. */
    private static final char PIPE = '|';
    /** The column name for the RNG. */
    private static final String COLUMN_RNG = "RNG";
    /** Constant for conversion of bytes to binary units, prefixed with a space. */
    private static final String[] BINARY_UNITS = {" B", " KiB", " MiB", " GiB", " TiB", " PiB", " EiB"};

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

    /** The results files. */
    @Parameters(arity = "1..*",
                description = "The results files.",
                paramLabel = "<file>")
    private List<File> resultsFiles = new ArrayList<>();

    /** The file output prefix. */
    @Option(names = {"-o", "--out"},
            description = "The output file (default: stdout).")
    private File fileOutput;

    /** The output format. */
    @Option(names = {"-f", "--format"},
            description = {"Output format (default: ${DEFAULT-VALUE}).",
                           "Valid values: ${COMPLETION-CANDIDATES}."})
    private ResultsCommand.OutputFormat outputFormat = OutputFormat.TXT;

    /** The flag to show failed tests. */
    @Option(names = {"--failed"},
            description = {"Output failed tests (support varies by format).",
                           "CSV: List individual test failures.",
                           "APT: Count of systematic test failures."})
    private boolean showFailedTests;

    /** The flag to include the Dieharder sums test. */
    @Option(names = {"--include-sums"},
            description = "Include Dieharder sums test.")
    private boolean includeDiehardSums;

    /** The common file path prefix used when outputting file paths. */
    @Option(names = {"--path-prefix"},
            description = {"Common path prefix.",
                           "If specified this will replace the common prefix from all " +
                           "files when the path is output, e.g. for the APT report."})
    private String pathPrefix = "";

    /** The flag to ignore partial results. */
    @Option(names = {"-i", "--ignore"},
            description = "Ignore partial results.")
    private boolean ignorePartialResults;

    /** The flag to delete partial results files. */
    @Option(names = {"--delete"},
            description = {"Delete partial results files.",
                           "This is not reversible!"})
    private boolean deletePartialResults;

    /**
     * The output mode for the results.
     */
    enum OutputFormat {
        /** Comma-Separated Values (CSV) output. */
        CSV,
        /** Almost Plain Text (APT) output. */
        APT,
        /** Text table output. */
        TXT,
        /** Systematic failures output. */
        FAILURES,
    }

    /**
     * The test application file format.
     */
    enum TestFormat {
        /** Dieharder. */
        DIEHARDER,
        /** Test U01. */
        TESTU01,
        /** PractRand. */
        PRACTRAND,
    }

    /**
     * Encapsulate the results of a test application.
     */
    private static class TestResult {
        /** The result file. */
        private final File resultFile;
        /** The random source. */
        private final RandomSource randomSource;
        /** Flag indicating the generator was bit reversed. */
        private final boolean bitReversed;
        /** The test application format. */
        private final TestFormat testFormat;
        /** The names of the failed tests. */
        private final List<String> failedTests = new ArrayList<>();
        /** The test application name. */
        private String testApplicationName;
        /**
         * Store the exit code.
         * Initialised to {@link Integer#MIN_VALUE}. Exit values are expected to be 8-bit numbers
         * with zero for success.
         */
        private int exitCode = Integer.MIN_VALUE;

        /**
         * @param resultFile the result file
         * @param randomSource the random source
         * @param bitReversed the bit reversed flag
         * @param testFormat the test format
         */
        TestResult(File resultFile,
                   RandomSource randomSource,
                   boolean bitReversed,
                   TestFormat testFormat) {
            this.resultFile = resultFile;
            this.randomSource = randomSource;
            this.bitReversed = bitReversed;
            this.testFormat = testFormat;
        }

        /**
         * Adds the failed test.
         *
         * @param testId the test id
         */
        void addFailedTest(String testId) {
            failedTests.add(testId);
        }

        /**
         * Gets the result file.
         *
         * @return the result file
         */
        File getResultFile() {
            return resultFile;
        }

        /**
         * Gets the random source.
         *
         * @return the random source
         */
        RandomSource getRandomSource() {
            return randomSource;
        }

        /**
         * Checks if the generator was bit reversed.
         *
         * @return true if bit reversed
         */
        boolean isBitReversed() {
            return bitReversed;
        }

        /**
         * Gets the test format.
         *
         * @return the test format
         */
        TestFormat getTestFormat() {
            return testFormat;
        }

        /**
         * Gets the failed tests.
         *
         * @return the failed tests
         */
        List<String> getFailedTests() {
            return failedTests;
        }

        /**
         * Gets the failure count.
         *
         * @return the failure count
         */
        int getFailureCount() {
            return failedTests.size();
        }

        /**
         * Gets the a failure summary string.
         *
         * <p>The default implementation is the count of the number of failures.
         * This will be negative if the test is not complete.</p>
         *
         * @return the failure summary
         */
        String getFailureSummaryString() {
            return (isComplete()) ? Integer.toString(failedTests.size()) : "-" + failedTests.size();
        }

        /**
         * Sets the test application name.
         *
         * @param testApplicationName the new test application name
         */
        void setTestApplicationName(String testApplicationName) {
            this.testApplicationName = testApplicationName;
        }

        /**
         * Gets the test application name.
         *
         * @return the test application name
         */
        String getTestApplicationName() {
            return testApplicationName == null ? String.valueOf(getTestFormat()) : testApplicationName;
        }

        /**
         * Checks if the test result is complete.
         * This is {@code true} only if the exit code was found and is zero.
         *
         * @return true if complete
         */
        boolean isComplete() {
            return exitCode == 0;
        }

        /**
         * Sets the exit code flag.
         *
         * @param exitCode the new exit code
         */
        void setExitCode(int exitCode) {
            this.exitCode = exitCode;
        }
    }

    /**
     * Encapsulate the results of a PractRand test application. This is a specialisation that
     * allows handling PractRand results which are linked to the output length used by the RNG.
     */
    private static class PractRandTestResult extends TestResult {
        /** The length of the RNG output used to generate failed tests. */
        private int lengthExponent;

        /**
         * @param resultFile the result file
         * @param randomSource the random source
         * @param bitReversed the bit reversed flag
         * @param testFormat the test format
         */
        PractRandTestResult(File resultFile, RandomSource randomSource, boolean bitReversed, TestFormat testFormat) {
            super(resultFile, randomSource, bitReversed, testFormat);
        }

        /**
         * Gets the length of the RNG output used to generate failed tests.
         * If this is zero then no failures occurred.
         *
         * @return the length exponent
         */
        int getLengthExponent() {
            return lengthExponent;
        }

        /**
         * Sets the length of the RNG output used to generate failed tests.
         *
         * @param lengthExponent the length exponent
         */
        void setLengthExponent(int lengthExponent) {
            this.lengthExponent = lengthExponent;
        }

        /**
         * {@inheritDoc}
         *
         * <p>The PractRand summary is the exponent of the length of byte output from the RNG where
         * a failure occurred.
         */
        @Override
        String getFailureSummaryString() {
            return lengthExponent == 0 ? "-" : Integer.toString(lengthExponent);
        }
    }

    /**
     * Reads the results files and outputs in the chosen format.
     */
    @Override
    public Void call() {
        LogUtils.setLogLevel(reusableOptions.logLevel);

        // Read the results
        final List<TestResult> results = readResults();

        if (deletePartialResults) {
            deleteIfIncomplete(results);
            return null;
        }

        try (OutputStream out = createOutputStream()) {
            switch (outputFormat) {
            case CSV:
                writeCSVData(out, results);
                break;
            case APT:
                writeAPT(out, results);
                break;
            case TXT:
                writeTXT(out, results);
                break;
            case FAILURES:
                writeFailures(out, results);
                break;
            default:
                throw new ApplicationException("Unknown output format: " + outputFormat);
            }
        } catch (final IOException ex) {
            throw new ApplicationException("IO error: " + ex.getMessage(), ex);
        }
        return null;
    }

    /**
     * Read the results.
     *
     * @return the results
     */
    private List<TestResult> readResults() {
        final ArrayList<TestResult> results = new ArrayList<>();
        for (final File resultFile : resultsFiles) {
            readResults(results, resultFile);
        }
        return results;
    }

    /**
     * Read the file and extract any test results.
     *
     * @param results Results.
     * @param resultFile Result file.
     * @throws ApplicationException If the results cannot be parsed.
     */
    private void readResults(List<TestResult> results,
                             File resultFile) {
        final List<String> contents = readFileContents(resultFile);
        // Files may have multiple test results per file (i.e. appended output)
        final List<List<String>> outputs = splitContents(contents);
        if (outputs.isEmpty()) {
            LogUtils.error("No test output in file: %s", resultFile);
        } else {
            for (final List<String> testOutput : outputs) {
                final TestResult result = readResult(resultFile, testOutput);
                if (!result.isComplete()) {
                    LogUtils.info("Partial results in file: %s", resultFile);
                    if (ignorePartialResults) {
                        continue;
                    }
                }
                results.add(result);
            }
        }
    }

    /**
     * Read the file contents.
     *
     * @param resultFile Result file.
     * @return the file contents
     * @throws ApplicationException If the file cannot be read.
     */
    private static List<String> readFileContents(File resultFile) {
        final ArrayList<String> contents = new ArrayList<>();
        try (BufferedReader reader = Files.newBufferedReader(resultFile.toPath())) {
            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
                contents.add(line);
            }
        } catch (final IOException ex) {
            throw new ApplicationException("Failed to read file contents: " + resultFile, ex);
        }
        return contents;
    }

    /**
     * Split the file contents into separate test output. This is used in the event
     * that results have been appended to the same file.
     *
     * @param contents File contents.
     * @return the test output
     */
    private static List<List<String>> splitContents(List<String> contents) {
        final ArrayList<List<String>> testOutputs = new ArrayList<>();
        // Assume each output begins with e.g. # RandomSource: SPLIT_MIX_64
        // Note each beginning.
        int begin = -1;
        for (int i = 0; i < contents.size(); i++) {
            if (RANDOM_SOURCE_PATTERN.matcher(contents.get(i)).matches()) {
                if (begin >= 0) {
                    testOutputs.add(contents.subList(begin, i));
                }
                begin = i;
            }
        }
        if (begin >= 0) {
            testOutputs.add(contents.subList(begin, contents.size()));
        }
        return testOutputs;
    }

    /**
     * Read the file into a test result.
     *
     * @param resultFile Result file.
     * @param testOutput Test output.
     * @return the test result
     * @throws ApplicationException If the result cannot be parsed.
     */
    private TestResult readResult(File resultFile,
                                  List<String> testOutput) {
        // Use an iterator for a single pass over the test output
        final ListIterator<String> iter = testOutput.listIterator();

        // Identify the RandomSource and bit reversed flag from the header:
        final RandomSource randomSource = getRandomSource(resultFile, iter);
        final boolean bitReversed = getBitReversed(resultFile, iter);

        // Identify the test application format. This may return null.
        final TestFormat testFormat = getTestFormat(resultFile, iter);

        // Read the application results
        final TestResult testResult = createTestResult(resultFile, randomSource, bitReversed, testFormat);
        if (testFormat == TestFormat.DIEHARDER) {
            readDieharder(iter, testResult);
        } else if (testFormat == TestFormat.TESTU01) {
            readTestU01(resultFile, iter, testResult);
        } else {
            readPractRand(iter, (PractRandTestResult) testResult);
        }
        return testResult;
    }

    /**
     * Creates the test result.
     *
     * @param resultFile Result file.
     * @param randomSource Random source.
     * @param bitReversed True if the random source was bit reversed.
     * @param testFormat Test format.
     * @return the test result
     */
    private static TestResult createTestResult(File resultFile, RandomSource randomSource,
                                               boolean bitReversed, TestFormat testFormat) {
        return testFormat == TestFormat.PRACTRAND ?
            new PractRandTestResult(resultFile, randomSource, bitReversed, testFormat) :
            new TestResult(resultFile, randomSource, bitReversed, testFormat);
    }

    /**
     * Gets the random source from the output header.
     *
     * @param resultFile Result file (for the exception message).
     * @param iter Iterator of the test output.
     * @return the random source
     * @throws ApplicationException If the RandomSource header line cannot be found.
     */
    private static RandomSource getRandomSource(File resultFile, Iterator<String> iter) {
        while (iter.hasNext()) {
            final Matcher matcher = RANDOM_SOURCE_PATTERN.matcher(iter.next());
            if (matcher.matches()) {
                return RandomSource.valueOf(matcher.group(1));
            }
        }
        throw new ApplicationException("Failed to find RandomSource header line: " + resultFile);
    }

    /**
     * Gets the bit-reversed flag from the output header.
     *
     * @param resultFile Result file (for the exception message).
     * @param iter Iterator of the test output.
     * @return the bit-reversed flag
     * @throws ApplicationException If the RNG header line cannot be found.
     */
    private static boolean getBitReversed(File resultFile, Iterator<String> iter) {
        while (iter.hasNext()) {
            final Matcher matcher = RNG_PATTERN.matcher(iter.next());
            if (matcher.matches()) {
                return matcher.group(1).contains(BIT_REVERSED);
            }
        }
        throw new ApplicationException("Failed to find RNG header line: " + resultFile);
    }

    /**
     * Gets the test format from the output. This scans the stdout produced by a test application.
     * If it is not recognised this may be a valid partial result or an unknown result. Throw
     * an exception if not allowing partial results, otherwise log an error.
     *
     * @param resultFile Result file (for the exception message).
     * @param iter Iterator of the test output.
     * @return the test format (or null)
     * @throws ApplicationException If the test format cannot be found.
     */
    private TestFormat getTestFormat(File resultFile, Iterator<String> iter) {
        while (iter.hasNext()) {
            final String line = iter.next();
            if (DIEHARDER_PATTERN.matcher(line).find()) {
                return TestFormat.DIEHARDER;
            }
            if (TESTU01_PATTERN.matcher(line).find()) {
                return TestFormat.TESTU01;
            }
            if (PRACTRAND_PATTERN.matcher(line).find()) {
                return TestFormat.PRACTRAND;
            }
        }
        if (!ignorePartialResults) {
            throw new ApplicationException("Failed to identify the test application format: " + resultFile);
        }
        LogUtils.error("Failed to identify the test application format: %s", resultFile);
        return null;
    }

    /**
     * Read the result output from the Dieharder test application.
     *
     * @param iter Iterator of the test output.
     * @param testResult Test result.
     */
    private void readDieharder(Iterator<String> iter,
                               TestResult testResult) {
        // Dieharder results are printed in-line using the following format:
        //#=============================================================================#
        //        test_name   |ntup| tsamples |psamples|  p-value |Assessment
        //#=============================================================================#
        //   diehard_birthdays|   0|       100|     100|0.97484422|  PASSED
        //   ...
        //        diehard_oqso|   0|   2097152|     100|0.00000000|  FAILED

        testResult.setTestApplicationName("Dieharder");

        // Identify any line containing FAILED and then get the test ID using
        // the first two columns (test_name + ntup).
        while (iter.hasNext()) {
            final String line = iter.next();
            if (DIEHARDER_FAILED_PATTERN.matcher(line).find()) {
                // Optionally include the flawed Dieharder sums test
                if (!includeDiehardSums && line.contains(DIEHARDER_SUMS)) {
                    continue;
                }
                final int index1 = line.indexOf('|');
                final int index2 = line.indexOf('|', index1 + 1);
                testResult.addFailedTest(line.substring(0, index1).trim() + ":" +
                                         line.substring(index1 + 1, index2).trim());
            } else if (findExitCode(testResult, line)) {
                return;
            }
        }
    }

    /**
     * Find the exit code in the line. Update the test result with the code if found.
     *
     * @param testResult Test result.
     * @param line Line from the test result output.
     * @return true, if the exit code was found
     */
    private static boolean findExitCode(TestResult testResult, String line) {
        final Matcher matcher = TEST_EXIT_PATTERN.matcher(line);
        if (matcher.find()) {
            testResult.setExitCode(Integer.parseInt(matcher.group(1)));
            return true;
        }
        return false;
    }

    /**
     * Read the result output from the Test U01 test application.
     *
     * <p>Test U01 outputs a summary of results at the end of the test output. If this cannot
     * be found the method will throw an exception unless partial results are allowed.</p>
     *
     * @param resultFile Result file (for the exception message).
     * @param iter Iterator of the test output.
     * @param testResult Test result.
     * @throws ApplicationException If the TestU01 summary cannot be found.
     */
    private void readTestU01(File resultFile,
                             ListIterator<String> iter,
                             TestResult testResult) {
        // Results are summarised at the end of the file:
        //========= Summary results of BigCrush =========
        //
        //Version:          TestU01 1.2.3
        //Generator:        stdin
        //Number of statistics:  155
        //Total CPU time:   06:14:50.43
        //The following tests gave p-values outside [0.001, 0.9990]:
        //(eps  means a value < 1.0e-300):
        //(eps1 means a value < 1.0e-15):
        //
        //      Test                          p-value
        //----------------------------------------------
        // 1  SerialOver, r = 0                eps
        // 3  CollisionOver, t = 2           1 - eps1
        // 5  CollisionOver, t = 3           1 - eps1
        // 7  CollisionOver, t = 7             eps

        // Identify the summary line
        final String testSuiteName = skipToTestU01Summary(resultFile, iter);

        // This may not be present if the results are not complete
        if (testSuiteName == null) {
            // Rewind
            while (iter.hasPrevious()) {
                iter.previous();
            }
            updateTestU01ApplicationName(iter, testResult);
            return;
        }

        setTestU01ApplicationName(testResult, testSuiteName);

        // Read test results using the entire line except the p-value for the test Id
        // Note:
        // This will count sub-parts of the same test as distinct failures.
        while (iter.hasNext()) {
            final String line = iter.next();
            final Matcher matcher = TESTU01_TEST_RESULT_PATTERN.matcher(line);
            if (matcher.find()) {
                testResult.addFailedTest(matcher.group(1).trim());
            } else if (findExitCode(testResult, line)) {
                return;
            }
        }
    }

    /**
     * Sets the Test U01 application name using the provide test suite name.
     *
     * @param testResult Test result.
     * @param testSuiteName Test suite name.
     */
    private static void setTestU01ApplicationName(TestResult testResult, String testSuiteName) {
        testResult.setTestApplicationName("TestU01 (" + testSuiteName + ")");
    }

    /**
     * Skip to the Test U01 result summary.
     *
     * <p>If this cannot be found the method will throw an exception unless partial results
     * are allowed.</p>
     *
     * @param resultFile Result file (for the exception message).
     * @param iter Iterator of the test output.
     * @return the name of the test suite
     * @throws ApplicationException If the TestU01 summary cannot be found.
     */
    private String skipToTestU01Summary(File resultFile, Iterator<String> iter) {
        final String testSuiteName = findMatcherGroup1(iter, TESTU01_SUMMARY_PATTERN);
        // Allow the partial result to be ignored
        if (testSuiteName != null || ignorePartialResults) {
            return testSuiteName;
        }
        throw new ApplicationException("Failed to identify the Test U01 result summary: " + resultFile);
    }

    /**
     * Update the test application name from the Test U01 results. This can be used to identify
     * the test suite from the start of the results in the event that the results summary has
     * not been output.
     *
     * @param iter Iterator of the test output.
     * @param testResult Test result.
     */
    private static void updateTestU01ApplicationName(Iterator<String> iter,
                                                     TestResult testResult) {
        final String testSuiteName = findMatcherGroup1(iter, TESTU01_STARTING_PATTERN);
        if (testSuiteName != null) {
            setTestU01ApplicationName(testResult, testSuiteName);
        }
    }

    /**
     * Create a matcher for each item in the iterator and if a match is identified return
     * group 1.
     *
     * @param iter Iterator of text to match.
     * @param pattern Pattern to match.
     * @return the string (or null)
     */
    private static String findMatcherGroup1(Iterator<String> iter,
                                            Pattern pattern) {
        while (iter.hasNext()) {
            final String line = iter.next();
            final Matcher matcher = pattern.matcher(line);
            if (matcher.find()) {
                return matcher.group(1);
            }
        }
        return null;
    }

    /**
     * Read the result output from the PractRand test application.
     *
     * @param iter Iterator of the test output.
     * @param testResult Test result.
     */
    private static void readPractRand(Iterator<String> iter,
                                      PractRandTestResult testResult) {
        // PractRand results are printed for blocks of byte output that double in size.
        // The results report 'unusual' and 'suspicious' output and the test stops
        // at the first failure.
        // Results are typically reported as the size of output that failed, e.g.
        // the JDK random fails at 256KiB.
        //
        // rng=RNG_stdin32, seed=0xfc6c7332
        // length= 128 kilobytes (2^17 bytes), time= 5.9 seconds
        //   no anomalies in 118 test result(s)
        //
        // rng=RNG_stdin32, seed=0xfc6c7332
        // length= 256 kilobytes (2^18 bytes), time= 7.6 seconds
        //   Test Name                         Raw       Processed     Evaluation
        //   [Low1/64]Gap-16:A                 R= +12.4  p =  8.7e-11   VERY SUSPICIOUS
        //   [Low1/64]Gap-16:B                 R= +13.4  p =  3.0e-11    FAIL
        //   [Low8/32]DC6-9x1Bytes-1           R=  +7.6  p =  5.7e-4   unusual
        //   ...and 136 test result(s) without anomalies

        testResult.setTestApplicationName("PractRand");

        // Store the exponent of the current output length.
        int exp = 0;

        // Identify any line containing FAIL and then get the test name using
        // the first token in the line.
        while (iter.hasNext()) {
            String line = iter.next();
            final Matcher matcher = PRACTRAND_OUTPUT_SIZE_PATTERN.matcher(line);
            if (matcher.find()) {
                // Store the current output length
                exp = Integer.parseInt(matcher.group(1));
            } else if (PRACTRAND_FAILED_PATTERN.matcher(line).find()) {
                // Record the output length where failures occurred.
                testResult.setLengthExponent(exp);
                // Add the failed test name. This does not include the length exponent
                // allowing meta-processing of systematic failures.
                // Remove initial whitespace
                line = line.trim();
                final int index = line.indexOf(' ');
                testResult.addFailedTest(line.substring(0, index));
            } else if (findExitCode(testResult, line)) {
                return;
            }
        }
    }

    /**
     * Delete any result file if incomplete.
     *
     * @param results Results.
     * @throws ApplicationException If a file could not be deleted.
     */
    private static void deleteIfIncomplete(List<TestResult> results) {
        results.forEach(ResultsCommand::deleteIfIncomplete);
    }

    /**
     * Delete the result file if incomplete.
     *
     * @param result Test result.
     * @throws ApplicationException If the file could not be deleted.
     */
    private static void deleteIfIncomplete(TestResult result) {
        if (!result.isComplete()) {
            try {
                Files.delete(result.getResultFile().toPath());
                LogUtils.info("Deleted file: %s", result.getResultFile());
            } catch (IOException ex) {
                throw new ApplicationException("Failed to delete file: " + result.getResultFile(), ex);
            }
        }
    }

    /**
     * Creates the output stream. This will not be buffered.
     *
     * @return the output stream
     */
    private OutputStream createOutputStream() {
        if (fileOutput != null) {
            try {
                Files.newOutputStream(fileOutput.toPath());
            } catch (final IOException ex) {
                throw new ApplicationException("Failed to create output: " + fileOutput, ex);
            }
        }
        return new FilterOutputStream(System.out) {
            @Override
            public void close() {
                // Do not close stdout
            }
        };
    }

    /**
     * Write the results to a table in Comma Separated Value (CSV) format.
     *
     * @param out Output stream.
     * @param results Results.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private void writeCSVData(OutputStream out,
                              List<TestResult> results) throws IOException {
        // Sort by columns
        Collections.sort(results, (o1, o2) -> {
            int result = Integer.compare(o1.getRandomSource().ordinal(), o2.getRandomSource().ordinal());
            if (result != 0) {
                return result;
            }
            result = Boolean.compare(o1.isBitReversed(), o2.isBitReversed());
            if (result != 0) {
                return result;
            }
            result = o1.getTestApplicationName().compareTo(o2.getTestApplicationName());
            if (result != 0) {
                return result;
            }
            return Integer.compare(o1.getFailureCount(), o2.getFailureCount());
        });

        try (BufferedWriter output = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) {
            output.write("RandomSource,Bit-reversed,Test,Failures");
            if (showFailedTests) {
                output.write(",Failed");
            }
            output.newLine();
            for (final TestResult result : results) {
                output.write(result.getRandomSource().toString());
                output.write(',');
                output.write(Boolean.toString(result.isBitReversed()));
                output.write(',');
                output.write(result.getTestApplicationName());
                output.write(',');
                output.write(result.getFailureSummaryString());
                // Optionally write out failed test names.
                if (showFailedTests) {
                    output.write(',');
                    output.write(result.getFailedTests().stream().collect(Collectors.joining("|")));
                }
                output.newLine();
            }
        }
    }

    /**
     * Write the results using the Almost Plain Text (APT) format for a table. This
     * table can be included in the documentation for the Commons RNG site.
     *
     * @param out Output stream.
     * @param results Results.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private void writeAPT(OutputStream out,
                          List<TestResult> results) throws IOException {
        // Identify all:
        // RandomSources, bit-reversed, test names,
        final List<RandomSource> randomSources = getRandomSources(results);
        final List<Boolean> bitReversed = getBitReversed(results);
        final List<String> testNames = getTestNames(results);

        // Identify the common path prefix to be replaced
        final int prefixLength = (pathPrefix.isEmpty()) ? 0 : findCommonPathPrefixLength(results);

        // Create a function to update the file path and then output the failure count
        // as a link to the file using the APT format.
        final Function<TestResult, String> toAPTString = result -> {
            String path = result.getResultFile().getPath();
            // Remove common path prefix
            path = path.substring(prefixLength);
            // Build the APT relative link
            final StringBuilder sb = new StringBuilder()
                .append("{{{").append(pathPrefix).append(path).append('}')
                .append(result.getFailureSummaryString()).append("}}");
            // Convert to web-link name separators
            for (int i = 0; i < sb.length(); i++) {
                if (sb.charAt(i) == BACK_SLASH) {
                    sb.setCharAt(i, FORWARD_SLASH);
                }
            }
            return sb.toString();
        };

        // Create columns for RandomSource, bit-reversed, each test name.
        // Make bit-reversed column optional if no generators are bit reversed.
        final boolean showBitReversedColumn = bitReversed.contains(Boolean.TRUE);

        final String header = createAPTHeader(showBitReversedColumn, testNames);
        final String separator = createAPTSeparator(header);

        // Output
        try (BufferedWriter output = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) {
            // For the first line using '*' (centre) character instead of '+' (left align)
            output.write(separator.replace('+', '*'));
            output.write(header);
            output.newLine();
            output.write(separator);

            final StringBuilder sb = new StringBuilder();

            // This will collate results for each combination of 'RandomSource + bitReversed'
            for (final RandomSource randomSource : randomSources) {
                for (final boolean reversed : bitReversed) {
                    // Highlight in bold a RNG with no systematic failures
                    boolean highlight = true;

                    // Buffer the column output
                    sb.setLength(0);

                    if (showBitReversedColumn) {
                        writeAPTColumn(sb, Boolean.toString(reversed), false);
                    }
                    for (final String testName : testNames) {
                        final List<TestResult> testResults = getTestResults(results, randomSource, reversed, testName);
                        String text = testResults.stream()
                                                 .map(toAPTString)
                                                 .collect(Collectors.joining(", "));
                        // Summarise the failures across all tests
                        final String summary = getFailuresSummary(testResults);
                        if (summary.length() != 0) {
                            // Identify RNGs with no systematic failures
                            highlight = false;
                            if (showFailedTests) {
                                // Add summary in brackets
                                text += " (" + summary + ")";
                            }
                        }
                        writeAPTColumn(sb, text, false);
                    }

                    output.write('|');
                    writeAPTColumn(output, randomSource.toString(), highlight);
                    output.write(sb.toString());
                    output.newLine();
                    output.write(separator);
                }
            }
        }
    }

    /**
     * Gets the random sources present in the results.
     *
     * @param results Results.
     * @return the random sources
     */
    private static List<RandomSource> getRandomSources(List<TestResult> results) {
        final EnumSet<RandomSource> set = EnumSet.noneOf(RandomSource.class);
        for (final TestResult result : results) {
            set.add(result.getRandomSource());
        }
        final ArrayList<RandomSource> list = new ArrayList<>(set);
        Collections.sort(list);
        return list;
    }

    /**
     * Gets the bit-reversed options present in the results.
     *
     * @param results Results.
     * @return the bit-reversed options
     */
    private static List<Boolean> getBitReversed(List<TestResult> results) {
        final ArrayList<Boolean> list = new ArrayList<>(2);
        if (results.isEmpty()) {
            // Default to no bit-reversed results
            list.add(Boolean.FALSE);
        } else {
            final boolean first = results.get(0).isBitReversed();
            list.add(first);
            for (final TestResult result : results) {
                if (first != result.isBitReversed()) {
                    list.add(!first);
                    break;
                }
            }
        }
        Collections.sort(list);
        return list;
    }

    /**
     * Gets the test names present in the results. These are returned in encountered order.
     *
     * @param results Results.
     * @return the test names
     */
    private static List<String> getTestNames(List<TestResult> results) {
        // Enforce encountered order with a linked hash set.
        final Set<String> set = new LinkedHashSet<>();
        for (final TestResult result : results) {
            set.add(result.getTestApplicationName());
        }
        return new ArrayList<>(set);
    }

    /**
     * Find the common path prefix for all result files. This is returned as the length of the
     * common prefix.
     *
     * @param results Results.
     * @return the length
     */
    private static int findCommonPathPrefixLength(List<TestResult> results) {
        if (results.isEmpty()) {
            return 0;
        }
        // Find the first prefix
        final String prefix1 = getPathPrefix(results.get(0));
        int length = prefix1.length();
        for (int i = 1; i < results.size() && length != 0; i++) {
            final String prefix2 = getPathPrefix(results.get(i));
            // Update
            final int size = Math.min(prefix2.length(), length);
            length = 0;
            while (length < size && prefix1.charAt(length) == prefix2.charAt(length)) {
                length++;
            }
        }
        return length;
    }

    /**
     * Gets the path prefix.
     *
     * @param testResult Test result.
     * @return the path prefix (or the empty string)
     */
    private static String getPathPrefix(TestResult testResult) {
        final String parent = testResult.getResultFile().getParent();
        return parent == null ? "" : parent;
    }

    /**
     * Creates the APT header.
     *
     * @param showBitReversedColumn Set to true to the show bit reversed column.
     * @param testNames Test names.
     * @return the header
     */
    private static String createAPTHeader(boolean showBitReversedColumn,
                                          List<String> testNames) {
        final StringBuilder sb = new StringBuilder(100).append("|| RNG identifier ||");
        if (showBitReversedColumn) {
            sb.append(" Bit-reversed ||");
        }
        for (final String name : testNames) {
            sb.append(' ').append(name).append(" ||");
        }
        return sb.toString();
    }

    /**
     * Creates the APT separator for each table row.
     *
     * <p>The separator is created using the '+' character to left align the columns.
     *
     * @param header Header.
     * @return the separator
     */
    private static String createAPTSeparator(String header) {
        // Replace everything with '-' except '|' which is replaced with "*-" for the first
        // character, "+-" for all other occurrences except "-+" at the end
        final StringBuilder sb = new StringBuilder(header);
        for (int i = 0; i < header.length(); i++) {
            if (sb.charAt(i) == PIPE) {
                sb.setCharAt(i, i == 0 ? '*' : '+');
                sb.setCharAt(i + 1,  '-');
            } else {
                sb.setCharAt(i,  '-');
            }
        }
        // Fix the end
        sb.setCharAt(header.length() - 2, '-');
        sb.setCharAt(header.length() - 1, '+');
        sb.append(System.lineSeparator());
        return sb.toString();
    }

    /**
     * Write the column text to the output.
     *
     * @param output Output.
     * @param text Text.
     * @param highlight If {@code true} highlight the text in bold.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void writeAPTColumn(Appendable output,
                                       String text,
                                       boolean highlight) throws IOException {
        output.append(' ');
        if (highlight) {
            output.append("<<");
        }
        output.append(text);
        if (highlight) {
            output.append(">>");
        }
        output.append(" |");
    }

    /**
     * Gets the test results that match the arguments.
     *
     * @param results Results.
     * @param randomSource Random source.
     * @param bitReversed Bit reversed flag.
     * @param testName Test name.
     * @return the matching results
     */
    private static List<TestResult> getTestResults(List<TestResult> results,
                                                   RandomSource randomSource,
                                                   boolean bitReversed,
                                                   String testName) {
        final ArrayList<TestResult> list = new ArrayList<>();
        for (final TestResult result : results) {
            if (result.getRandomSource() == randomSource &&
                result.bitReversed == bitReversed &&
                result.getTestApplicationName().equals(testName)) {
                list.add(result);
            }
        }
        return list;
    }

    /**
     * Gets the systematic failures (tests that fail in every test result).
     *
     * @param results Results.
     * @return the systematic failures
     */
    private static List<String> getSystematicFailures(List<TestResult> results) {
        final HashMap<String, Integer> map = new HashMap<>();
        for (final TestResult result : results) {
            // Ignore partial results
            if (!result.isComplete()) {
                continue;
            }
            // Some named tests can fail more than once on different statistics.
            // For example TestU01 BigCrush LongestHeadRun can output in the summary:
            // 86  LongestHeadRun, r = 0            eps
            // 86  LongestHeadRun, r = 0          1 - eps1
            // This will be counted as 2 failed tests. For the purpose of systematic
            // failures the name of the test is the same and should be counted once.
            final HashSet<String> unique = new HashSet<>(result.getFailedTests());
            for (String test : unique) {
                map.merge(test, 1, (i, j) -> i + j);
            }
        }
        final int completeCount = (int) results.stream().filter(TestResult::isComplete).count();
        final List<String> list = map.entrySet().stream()
                                                .filter(e -> e.getValue() == completeCount)
                                                .map(Entry::getKey)
                                                .collect(Collectors.toCollection(
                                                    (Supplier<List<String>>) ArrayList::new));
        // Special case for PractRand. Add the maximum RNG output length before failure.
        // This is because some PractRand tests may not be counted as systematic failures
        // as they have not been run to the same output length due to earlier failure of
        // another test.
        final int max = getMaxLengthExponent(results);
        if (max != 0) {
            list.add(bytesToString(max));
        }
        return list;
    }

    /**
     * Gets the maximum length exponent from the PractRand results if <strong>all</strong> failed.
     * Otherwise return zero (i.e. some passed the full length of the test).
     *
     * <p>This method excludes those results that are not complete. It assumes all complete
     * tests are for the same length of RNG output. Thus if all failed then the max exponent
     * is the systematic failure length.</p>
     *
     * @param results Results.
     * @return the maximum length exponent (or zero)
     */
    private static int getMaxLengthExponent(List<TestResult> results) {
        if (results.isEmpty()) {
            return 0;
        }
        // [0] = count of zeros
        // [1] = max non-zero
        final int[] data = new int[2];
        results.stream()
               .filter(TestResult::isComplete)
               .filter(r -> r instanceof PractRandTestResult)
               .mapToInt(r -> ((PractRandTestResult) r).getLengthExponent())
               .forEach(i -> {
                   if (i == 0) {
                       // Count results that passed
                       data[0]++;
                   } else {
                       // Find the max of the failures
                       data[1] = Math.max(i, data[1]);
                   }
               });
        // If all failed (i.e. no zeros) then return the max, otherwise zero.
        return data[0] == 0 ? data[1] : 0;
    }

    /**
     * Gets a summary of the failures across all results. The text is empty if there are no
     * failures to report.
     *
     * <p>For Dieharder and TestU01 this is the number of systematic failures (tests that fail
     * in every test result). For PractRand it is the maximum byte output size that was reached
     * before failure.
     *
     * <p>It is assumed all the results are for the same test suite.</p>
     *
     * @param results Results.
     * @return the failures summary
     */
    private static String getFailuresSummary(List<TestResult> results) {
        if (results.isEmpty()) {
            return "";
        }
        if (results.get(0).getTestFormat() == TestFormat.PRACTRAND) {
            final int max = getMaxLengthExponent(results);
            return max == 0 ? "" : bytesToString(max);
        }
        final int count = getSystematicFailures(results).size();
        return count == 0 ? "" : Integer.toString(count);
    }

    /**
     * Write the results as a text table.
     *
     * @param out Output stream.
     * @param results Results.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void writeTXT(OutputStream out,
                                 List<TestResult> results) throws IOException {
        // Identify all:
        // RandomSources, bit-reversed, test names,
        final List<RandomSource> randomSources = getRandomSources(results);
        final List<Boolean> bitReversed = getBitReversed(results);
        final List<String> testNames = getTestNames(results);

        // Create columns for RandomSource, bit-reversed, each test name.
        // Make bit-reversed column optional if no generators are bit reversed.
        final boolean showBitReversedColumn = bitReversed.contains(Boolean.TRUE);

        final List<List<String>> columns = createTXTColumns(testNames, showBitReversedColumn);

        // Add all data
        // This will collate results for each combination of 'RandomSource + bitReversed'
        for (final RandomSource randomSource : randomSources) {
            for (final boolean reversed : bitReversed) {
                int i = 0;
                columns.get(i++).add(randomSource.toString());
                if (showBitReversedColumn) {
                    columns.get(i++).add(Boolean.toString(reversed));
                }
                for (final String testName : testNames) {
                    final List<TestResult> testResults = getTestResults(results, randomSource,
                            reversed, testName);
                    columns.get(i++).add(testResults.stream()
                                                    .map(TestResult::getFailureSummaryString)
                                                    .collect(Collectors.joining(",")));
                    columns.get(i++).add(getFailuresSummary(testResults));
                }
            }
        }

        writeColumns(out, columns);
    }

    /**
     * Creates the columns for the text output.
     *
     * @param testNames the test names
     * @param showBitReversedColumn Set to true to show the bit reversed column
     * @return the list of columns
     */
    private static List<List<String>> createTXTColumns(final List<String> testNames,
        final boolean showBitReversedColumn) {
        final ArrayList<List<String>> columns = new ArrayList<>();
        columns.add(createColumn(COLUMN_RNG));
        if (showBitReversedColumn) {
            columns.add(createColumn(BIT_REVERSED));
        }
        for (final String testName : testNames) {
            columns.add(createColumn(testName));
            columns.add(createColumn("∩"));
        }
        return columns;
    }

    /**
     * Creates the column.
     *
     * @param columnName Column name.
     * @return the list
     */
    private static List<String> createColumn(String columnName) {
        final ArrayList<String> list = new ArrayList<>();
        list.add(columnName);
        return list;
    }


    /**
     * Creates the text format from column widths.
     *
     * @param columns Columns.
     * @return the text format string
     */
    private static String createTextFormatFromColumnWidths(final List<List<String>> columns) {
        final StringBuilder sb = new StringBuilder();
        try (Formatter formatter = new Formatter(sb)) {
            for (int i = 0; i < columns.size(); i++) {
                if (i != 0) {
                    sb.append('\t');
                }
                formatter.format("%%-%ds", getColumnWidth(columns.get(i)));
            }
        }
        sb.append(System.lineSeparator());
        return sb.toString();
    }

    /**
     * Gets the column width using the maximum length of the column items.
     *
     * @param column Column.
     * @return the column width
     */
    private static int getColumnWidth(List<String> column) {
        int width = 0;
        for (final String text : column) {
            width = Math.max(width, text.length());
        }
        return width;
    }

    /**
     * Write the columns as fixed width text to the output.
     *
     * @param out Output stream.
     * @param columns Columns
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void writeColumns(OutputStream out,
                                     List<List<String>> columns) throws IOException {
        // Create format using the column widths
        final String format = createTextFormatFromColumnWidths(columns);

        // Output
        try (BufferedWriter output = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
             Formatter formatter = new Formatter(output)) {
            final int rows = columns.get(0).size();
            final Object[] args = new Object[columns.size()];
            for (int row = 0; row < rows; row++) {
                for (int i = 0; i < args.length; i++) {
                    args[i] = columns.get(i).get(row);
                }
                formatter.format(format, args);
            }
        }
    }

    /**
     * Write the systematic failures as a text table.
     *
     * @param out Output stream.
     * @param results Results.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void writeFailures(OutputStream out,
                                      List<TestResult> results) throws IOException {
        // Identify all:
        // RandomSources, bit-reversed, test names,
        final List<RandomSource> randomSources = getRandomSources(results);
        final List<Boolean> bitReversed = getBitReversed(results);
        final List<String> testNames = getTestNames(results);

        // Create columns for RandomSource, bit-reversed, each test name.
        // Make bit-reversed column optional if no generators are bit reversed.
        final boolean showBitReversedColumn = bitReversed.contains(Boolean.TRUE);

        final List<List<String>> columns = createFailuresColumns(testNames, showBitReversedColumn);

        final AlphaNumericComparator cmp = new AlphaNumericComparator();

        // Add all data for each combination of 'RandomSource + bitReversed'
        for (final RandomSource randomSource : randomSources) {
            for (final boolean reversed : bitReversed) {
                for (final String testName : testNames) {
                    final List<TestResult> testResults = getTestResults(results, randomSource,
                            reversed, testName);
                    final List<String> failures = getSystematicFailures(testResults);
                    if (failures.isEmpty()) {
                        continue;
                    }
                    Collections.sort(failures, cmp);
                    for (String failed : failures) {
                        int i = 0;
                        columns.get(i++).add(randomSource.toString());
                        if (showBitReversedColumn) {
                            columns.get(i++).add(Boolean.toString(reversed));
                        }
                        columns.get(i++).add(testName);
                        columns.get(i).add(failed);
                    }
                }
            }
        }

        writeColumns(out, columns);
    }

    /**
     * Creates the columns for the failures output.
     *
     * @param testNames the test names
     * @param showBitReversedColumn Set to true to show the bit reversed column
     * @return the list of columns
     */
    private static List<List<String>> createFailuresColumns(final List<String> testNames,
        final boolean showBitReversedColumn) {
        final ArrayList<List<String>> columns = new ArrayList<>();
        columns.add(createColumn(COLUMN_RNG));
        if (showBitReversedColumn) {
            columns.add(createColumn(BIT_REVERSED));
        }
        columns.add(createColumn("Test Suite"));
        columns.add(createColumn("Test"));
        return columns;
    }

    /**
     * Convert bytes to a human readable string. The byte size is expressed in powers of 2.
     * The output units use the ISO binary prefix for increments of 2<sup>10</sup> or 1024.
     *
     * <p>This is a utility function used for reporting PractRand output sizes.
     * Example output:
     *
     * <pre>
     *            exponent       Binary
     *                   0          0 B
     *                  10        1 KiB
     *                  13        8 KiB
     *                  20        1 MiB
     *                  27      128 MiB
     *                  30        1 GiB
     *                  40        1 TiB
     *                  50        1 PiB
     *                  60        1 EiB
     * </pre>
     *
     * @param exponent Exponent of the byte size (i.e. 2^exponent).
     * @return the string
     */
    static String bytesToString(int exponent) {
        final int unit = exponent / 10;
        final int size = 1 << (exponent - 10 * unit);
        return size + BINARY_UNITS[unit];
    }
}
