/*
 * 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.core.source64;

import org.apache.commons.rng.core.util.NumberFactory;
import org.apache.commons.rng.core.BaseProvider;

/**
 * Base class for all implementations that provide a {@code long}-based
 * source randomness.
 */
public abstract class LongProvider
    extends BaseProvider
    implements RandomLongSource {

    /**
     * Provides a bit source for booleans.
     *
     * <p>A cached value from a call to {@link #nextLong()}.
     */
    private long booleanSource; // Initialised as 0

    /**
     * The bit mask of the boolean source to obtain the boolean bit.
     *
     * <p>The bit mask contains a single bit set. This begins at the least
     * significant bit and is gradually shifted upwards until overflow to zero.
     *
     * <p>When zero a new boolean source should be created and the mask set to the
     * least significant bit (i.e. 1).
     */
    private long booleanBitMask; // Initialised as 0

    /**
     * Provides a source for ints.
     *
     * <p>A cached value from a call to {@link #nextLong()}.
     */
    private long intSource;

    /** Flag to indicate an int source has been cached. */
    private boolean cachedIntSource; // Initialised as false

    /**
     * Creates a new instance.
     */
    public LongProvider() {
        super();
    }

    /**
     * Creates a new instance copying the state from the source.
     *
     * <p>This provides base functionality to allow a generator to create a copy, for example
     * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider
     * JumpableUniformRandomProvider} interface.
     *
     * @param source Source to copy.
     * @since 1.3
     */
    protected LongProvider(LongProvider source) {
        booleanSource = source.booleanSource;
        booleanBitMask = source.booleanBitMask;
        intSource = source.intSource;
        cachedIntSource = source.cachedIntSource;
    }

    /**
     * Reset the cached state used in the default implementation of {@link #nextBoolean()}
     * and {@link #nextInt()}.
     *
     * <p>This should be used when the state is no longer valid, for example after a jump
     * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider
     * JumpableUniformRandomProvider} interface.</p>
     *
     * @since 1.3
     */
    protected void resetCachedState() {
        booleanSource = 0L;
        booleanBitMask = 0L;
        intSource = 0L;
        cachedIntSource = false;
    }

    /** {@inheritDoc} */
    @Override
    protected byte[] getStateInternal() {
        // Pack the boolean inefficiently as a long
        final long[] state = {booleanSource,
                              booleanBitMask,
                              intSource,
                              cachedIntSource ? 1 : 0 };
        return composeStateInternal(NumberFactory.makeByteArray(state),
                                    super.getStateInternal());
    }

    /** {@inheritDoc} */
    @Override
    protected void setStateInternal(byte[] s) {
        final byte[][] c = splitStateInternal(s, 32);
        final long[] state = NumberFactory.makeLongArray(c[0]);
        booleanSource   = state[0];
        booleanBitMask  = state[1];
        intSource       = state[2];
        // Non-zero is true
        cachedIntSource = state[3] != 0;
        super.setStateInternal(c[1]);
    }

    /** {@inheritDoc} */
    @Override
    public long nextLong() {
        return next();
    }

    /** {@inheritDoc} */
    @Override
    public int nextInt() {
        // Directly store and use the long value as a source for ints
        if (cachedIntSource) {
            // Consume the cache value
            cachedIntSource = false;
            // Return the lower 32 bits
            return NumberFactory.extractLo(intSource);
        }
        // Fill the cache
        cachedIntSource = true;
        intSource = nextLong();
        // Return the upper 32 bits
        return NumberFactory.extractHi(intSource);
    }

    /** {@inheritDoc} */
    @Override
    public double nextDouble() {
        return NumberFactory.makeDouble(nextLong());
    }

    /** {@inheritDoc} */
    @Override
    public boolean nextBoolean() {
        // Shift up. This will eventually overflow and become zero.
        booleanBitMask <<= 1;
        // The mask will either contain a single bit or none.
        if (booleanBitMask == 0) {
            // Set the least significant bit
            booleanBitMask = 1;
            // Get the next value
            booleanSource = nextLong();
        }
        // Return if the bit is set
        return (booleanSource & booleanBitMask) != 0;
    }

    /** {@inheritDoc} */
    @Override
    public float nextFloat() {
        return NumberFactory.makeFloat(nextInt());
    }

    /** {@inheritDoc} */
    @Override
    public void nextBytes(byte[] bytes) {
        nextBytesFill(this, bytes, 0, bytes.length);
    }

    /** {@inheritDoc} */
    @Override
    public void nextBytes(byte[] bytes,
                          int start,
                          int len) {
        checkIndex(0, bytes.length - 1, start);
        checkIndex(0, bytes.length - start, len);

        nextBytesFill(this, bytes, start, len);
    }

    /**
     * Generates random bytes and places them into a user-supplied array.
     *
     * <p>
     * The array is filled with bytes extracted from random {@code long} values.
     * This implies that the number of random bytes generated may be larger than
     * the length of the byte array.
     * </p>
     *
     * @param source Source of randomness.
     * @param bytes Array in which to put the generated bytes. Cannot be null.
     * @param start Index at which to start inserting the generated bytes.
     * @param len Number of bytes to insert.
     */
    static void nextBytesFill(RandomLongSource source,
                              byte[] bytes,
                              int start,
                              int len) {
        int index = start; // Index of first insertion.

        // Index of first insertion plus multiple of 8 part of length
        // (i.e. length with 3 least significant bits unset).
        final int indexLoopLimit = index + (len & 0x7ffffff8);

        // Start filling in the byte array, 8 bytes at a time.
        while (index < indexLoopLimit) {
            final long random = source.next();
            bytes[index++] = (byte) random;
            bytes[index++] = (byte) (random >>> 8);
            bytes[index++] = (byte) (random >>> 16);
            bytes[index++] = (byte) (random >>> 24);
            bytes[index++] = (byte) (random >>> 32);
            bytes[index++] = (byte) (random >>> 40);
            bytes[index++] = (byte) (random >>> 48);
            bytes[index++] = (byte) (random >>> 56);
        }

        final int indexLimit = start + len; // Index of last insertion + 1.

        // Fill in the remaining bytes.
        if (index < indexLimit) {
            long random = source.next();
            while (true) {
                bytes[index++] = (byte) random;
                if (index < indexLimit) {
                    random >>>= 8;
                } else {
                    break;
                }
            }
        }
    }
}
