/*
 * 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 java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteOrder;

/**
 * A specialised data output class that combines the functionality of
 * {@link java.io.DataOutputStream DataOutputStream} and
 * {@link java.io.BufferedOutputStream BufferedOutputStream} to write byte data from a RNG
 * to an OutputStream. Large blocks of byte data are written in a single operation for efficiency.
 * The byte data endianness can be configured.
 *
 * <p>This class is the functional equivalent of:</p>
 *
 * <pre>
 * <code>
 * OutputStream out = ...
 * UniformRandomProvider rng = ...
 * int size = 2048;
 * DataOutputStream sink = new DataOutputStream(new BufferedOutputStream(out, size * 4));
 * for (int i = 0; i < size; i++) {
 *    sink.writeInt(rng.nextInt());
 * }
 *
 * // Replaced with
 * RngDataOutput output = RngDataOutput.ofInt(out, size, ByteOrder.BIG_ENDIAN);
 * output.write(rng);
 * </code>
 * </pre>
 *
 * <p>Use of this class avoids the synchronized write operations in
 * {@link java.io.BufferedOutputStream BufferedOutputStream}. In particular it avoids the
 * 4 synchronized write operations to
 * {@link java.io.BufferedOutputStream#write(int) BufferedOutputStream#write(int)} that
 * occur for each {@code int} value that is written to
 * {@link java.io.DataOutputStream#writeInt(int) DataOutputStream#writeInt(int)}.</p>
 *
 * <p>This class has adaptors to write the long output from a RNG to two int values.
 * To match the caching implementation in the the core LongProvider class this is tested
 * to output int values in the same order as an instance of the LongProvider. Currently
 * this outputs in order: low 32-bits, high 32-bits.
 */
abstract class RngDataOutput implements Closeable {
    /** The data buffer. */
    protected final byte[] buffer;

    /** The underlying output stream. */
    private final OutputStream out;

    /**
     * Write big-endian {@code int} data.
     * <pre>
     * 3210  ->  3210
     * </pre>
     */
    private static class BIntRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        BIntRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 4) {
                writeIntBE(i, rng.nextInt());
            }
        }
    }

    /**
     * Write little-endian {@code int} data.
     * <pre>
     * 3210  ->  0123
     * </pre>
     */
    private static class LIntRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        LIntRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 4) {
                writeIntLE(i, rng.nextInt());
            }
        }
    }

    /**
     * Write big-endian {@code long} data.
     * <pre>
     * 76543210  ->  76543210
     * </pre>
     */
    private static class BLongRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        BLongRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 8) {
                writeLongBE(i, rng.nextLong());
            }
        }
    }

    /**
     * Write little-endian {@code long} data.
     * <pre>
     * 76543210  ->  01234567
     * </pre>
     */
    private static class LLongRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        LLongRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 8) {
                writeLongLE(i, rng.nextLong());
            }
        }
    }

    /**
     * Write {@code long} data as two little-endian {@code int} values, high 32-bits then
     * low 32-bits.
     * <pre>
     * 76543210  ->  4567  0123
     * </pre>
     *
     * <p>This is a specialisation that allows the Java big-endian representation to be split
     * into two little-endian values in the original order of upper then lower bits. In
     * comparison the {@link LLongRngDataOutput} will output the same data as:
     *
     * <pre>
     * 76543210  ->  0123  4567
     * </pre>
     */
    private static class LLongAsIntRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        LLongAsIntRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 8) {
                writeLongAsHighLowIntLE(i, rng.nextLong());
            }
        }
    }

    /**
     * Write {@code long} data as two big-endian {@code int} values, low 32-bits then
     * high 32-bits.
     * <pre>
     * 76543210  ->  3210  7654
     * </pre>
     *
     * <p>This is a specialisation that allows the Java big-endian representation to be split
     * into two big-endian values in the original order of lower then upper bits. In
     * comparison the {@link BLongRngDataOutput} will output the same data as:
     *
     * <pre>
     * 76543210  ->  7654  3210
     * </pre>
     */
    private static class BLongAsLoHiIntRngDataOutput extends RngDataOutput {
        /**
         * @param out Output stream.
         * @param size Buffer size.
         */
        BLongAsLoHiIntRngDataOutput(OutputStream out, int size) {
            super(out, size);
        }

        @Override
        public void fillBuffer(UniformRandomProvider rng) {
            for (int i = 0; i < buffer.length; i += 8) {
                writeLongAsLowHighIntBE(i, rng.nextLong());
            }
        }
    }

    /**
     * Create a new instance.
     *
     * @param out Output stream.
     * @param size Buffer size.
     */
    RngDataOutput(OutputStream out, int size) {
        this.out = out;
        buffer = new byte[size];
    }

    /**
     * Write the configured amount of byte data from the specified RNG to the output.
     *
     * @param rng Source of randomness.
     * @exception IOException if an I/O error occurs.
     */
    public void write(UniformRandomProvider rng) throws IOException {
        fillBuffer(rng);
        out.write(buffer);
    }

    /**
     * Fill the buffer from the specified RNG.
     *
     * @param rng Source of randomness.
     */
    public abstract void fillBuffer(UniformRandomProvider rng);

    /**
     * Writes an {@code int} to the buffer as four bytes, high byte first (big-endian).
     *
     * @param index the index to start writing.
     * @param value an {@code int} to be written.
     */
    final void writeIntBE(int index, int value) {
        buffer[index    ] = (byte) (value >>> 24);
        buffer[index + 1] = (byte) (value >>> 16);
        buffer[index + 2] = (byte) (value >>> 8);
        buffer[index + 3] = (byte) value;
    }

    /**
     * Writes an {@code int} to the buffer as four bytes, low byte first (little-endian).
     *
     * @param index the index to start writing.
     * @param value an {@code int} to be written.
     */
    final void writeIntLE(int index, int value) {
        buffer[index    ] = (byte) value;
        buffer[index + 1] = (byte) (value >>> 8);
        buffer[index + 2] = (byte) (value >>> 16);
        buffer[index + 3] = (byte) (value >>> 24);
    }

    /**
     * Writes an {@code long} to the buffer as eight bytes, high byte first (big-endian).
     *
     * @param index the index to start writing.
     * @param value an {@code long} to be written.
     */
    final void writeLongBE(int index, long value) {
        buffer[index    ] = (byte) (value >>> 56);
        buffer[index + 1] = (byte) (value >>> 48);
        buffer[index + 2] = (byte) (value >>> 40);
        buffer[index + 3] = (byte) (value >>> 32);
        buffer[index + 4] = (byte) (value >>> 24);
        buffer[index + 5] = (byte) (value >>> 16);
        buffer[index + 6] = (byte) (value >>> 8);
        buffer[index + 7] = (byte) value;
    }

    /**
     * Writes an {@code long} to the buffer as eight bytes, low byte first (little-endian).
     *
     * @param index the index to start writing.
     * @param value an {@code long} to be written.
     */
    final void writeLongLE(int index, long value) {
        buffer[index    ] = (byte) value;
        buffer[index + 1] = (byte) (value >>> 8);
        buffer[index + 2] = (byte) (value >>> 16);
        buffer[index + 3] = (byte) (value >>> 24);
        buffer[index + 4] = (byte) (value >>> 32);
        buffer[index + 5] = (byte) (value >>> 40);
        buffer[index + 6] = (byte) (value >>> 48);
        buffer[index + 7] = (byte) (value >>> 56);
    }

    /**
     * Writes an {@code long} to the buffer as two integers of four bytes, each
     * low byte first (little-endian). The long is written as the high 32-bits,
     * then the low 32-bits.
     *
     * <p>Note: A LowHigh little-endian output is the same as {@link #writeLongLE(int, long)}.
     *
     * @param index the index to start writing.
     * @param value an {@code long} to be written.
     */
    final void writeLongAsHighLowIntLE(int index, long value) {
        // high
        buffer[index    ] = (byte) (value >>> 32);
        buffer[index + 1] = (byte) (value >>> 40);
        buffer[index + 2] = (byte) (value >>> 48);
        buffer[index + 3] = (byte) (value >>> 56);
        // low
        buffer[index + 4] = (byte) value;
        buffer[index + 5] = (byte) (value >>> 8);
        buffer[index + 6] = (byte) (value >>> 16);
        buffer[index + 7] = (byte) (value >>> 24);
    }

    /**
     * Writes an {@code long} to the buffer as two integers of four bytes, each
     * high byte first (big-endian). The long is written as the low 32-bits,
     * then the high 32-bits.
     *
     * <p>Note: A HighLow big-endian output is the same as {@link #writeLongBE(int, long)}.
     *
     * @param index the index to start writing.
     * @param value an {@code long} to be written.
     */
    final void writeLongAsLowHighIntBE(int index, long value) {
        // low
        buffer[index    ] = (byte) (value >>> 24);
        buffer[index + 1] = (byte) (value >>> 16);
        buffer[index + 2] = (byte) (value >>> 8);
        buffer[index + 3] = (byte) value;
        // high
        buffer[index + 4] = (byte) (value >>> 56);
        buffer[index + 5] = (byte) (value >>> 48);
        buffer[index + 6] = (byte) (value >>> 40);
        buffer[index + 7] = (byte) (value >>> 32);
    }

    @Override
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            ostream.flush();
        }
    }

    /**
     * Create a new instance to write batches of data from
     * {@link UniformRandomProvider#nextInt()} to the specified output.
     *
     * @param out Output stream.
     * @param size Number of values to write.
     * @param byteOrder Byte order.
     * @return the data output
     */
    @SuppressWarnings("resource")
    static RngDataOutput ofInt(OutputStream out, int size, ByteOrder byteOrder) {
        // Ensure the buffer is positive and a factor of 4
        final int bytes = Math.max(size * 4, 4);
        return byteOrder == ByteOrder.LITTLE_ENDIAN ?
            new LIntRngDataOutput(out, bytes) :
            new BIntRngDataOutput(out, bytes);
    }

    /**
     * Create a new instance to write batches of data from
     * {@link UniformRandomProvider#nextLong()} to the specified output.
     *
     * @param out Output stream.
     * @param size Number of values to write.
     * @param byteOrder Byte order.
     * @return the data output
     */
    @SuppressWarnings("resource")
    static RngDataOutput ofLong(OutputStream out, int size, ByteOrder byteOrder) {
        // Ensure the buffer is positive and a factor of 8
        final int bytes = Math.max(size * 8, 8);
        return byteOrder == ByteOrder.LITTLE_ENDIAN ?
            new LLongRngDataOutput(out, bytes) :
            new BLongRngDataOutput(out, bytes);
    }

    /**
     * Create a new instance to write batches of data from
     * {@link UniformRandomProvider#nextLong()} to the specified output as two sequential
     * {@code int} values, high 32-bits then low 32-bits.
     *
     * <p>This will output the following bytes:</p>
     *
     * <pre>
     * // Little-endian
     * 76543210  ->  4567  0123
     *
     * // Big-endian
     * 76543210  ->  7654  3210
     * </pre>
     *
     * <p>This ensures the output from the generator is the original upper then lower order bits
     * for each endianess.
     *
     * @param out Output stream.
     * @param size Number of values to write.
     * @param byteOrder Byte order.
     * @return the data output
     */
    @SuppressWarnings("resource")
    static RngDataOutput ofLongAsHLInt(OutputStream out, int size, ByteOrder byteOrder) {
        // Ensure the buffer is positive and a factor of 8
        final int bytes = Math.max(size * 8, 8);
        return byteOrder == ByteOrder.LITTLE_ENDIAN ?
            new LLongAsIntRngDataOutput(out, bytes) :
            new BLongRngDataOutput(out, bytes);
    }

    /**
     * Create a new instance to write batches of data from
     * {@link UniformRandomProvider#nextLong()} to the specified output as two sequential
     * {@code int} values, low 32-bits then high 32-bits.
     *
     * <p>This will output the following bytes:</p>
     *
     * <pre>
     * // Little-endian
     * 76543210  ->  0123  4567
     *
     * // Big-endian
     * 76543210  ->  3210  7654
     * </pre>
     *
     * <p>This ensures the output from the generator is the original lower then upper order bits
     * for each endianess.
     *
     * @param out Output stream.
     * @param size Number of values to write.
     * @param byteOrder Byte order.
     * @return the data output
     */
    @SuppressWarnings("resource")
    static RngDataOutput ofLongAsLHInt(OutputStream out, int size, ByteOrder byteOrder) {
        // Ensure the buffer is positive and a factor of 8
        final int bytes = Math.max(size * 8, 8);
        return byteOrder == ByteOrder.LITTLE_ENDIAN ?
            new LLongRngDataOutput(out, bytes) :
            new BLongAsLoHiIntRngDataOutput(out, bytes);
    }
}
