# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Generating random variables by using an entropy buffer.

A class for generating random numbers and permutations, by fetching entropy
from a file.
"""

import logging as log
import sys
from math import ceil as _ceil
from math import log as _log


class strong_random():

    def __init__(self):
        """Initialize an instance.

        Entropy buffer is empty by default.
        """

        self.buffer = []
        self.buffername = ""

    def load(self, input_file):
        """Load entropy buffer from an external file.

        Currently only supports numpy array of 8-bit values.
        """

        if self.buffername == input_file:
            log.error("Entropy buffer " + input_file + " can't be loaded twice.")
            sys.exit(1)

        with open(input_file, 'r') as fp:
            for line in fp:
                x = int(line)
                if x in range(256):
                    self.buffer.append(x)
                else:
                    log.error("Read value not in range 0 - 255.")
                    sys.exit(1)
        self.buffername = input_file

    def size(self):
        """Size of the buffer.
        """

        return len(self.buffer)

    def printstatus(self):
        """Prints the number of remaining bytes in the buffer.

        May be useful for testing and debugging.
        """

        if self.isempty():
            print('Buffer is empty.')
        else:
            print("Buffer remaining:", len(self.buffer), "bytes.")

    def isempty(self):
        """Checks if the buffer is empty.
        """

        return (not self.buffer)

    def fetchbyte(self):
        """Fetches the next byte from the buffer.

        Used by getrandbits().
        If the buffer is already empty, raises an error and exits.
        """

        if self.isempty():
            log.error("Entropy buffer empty.")
            sys.exit(1)
        else:
            random_byte = self.buffer.pop(0)
            return (random_byte)

    def getrandbits(self, n_bits):
        """Fetches n_bits next bits from a buffer.

        Always fetches a whole number of bytes. Unused bits are discarded.
        """

        bitsleft = n_bits
        R = 0
        while (bitsleft > 0):
            random_byte = int(self.fetchbyte())
            if (bitsleft > 8):
                R = (R << 8) | random_byte
                bitsleft = bitsleft - 8
            else:
                random_byte >>= 8 - bitsleft
                R = (R << bitsleft) | random_byte
                bitsleft = 0
        assert R >= 0
        return (R)

    def randbelow(self, n):
        """Generates a random integer smaller than n.

        Uses getrandbits() to generate enough random bits. Repeats until the
        resulting number is smaller than n. The probability of this is more
        than 50% in each loop iteration.
        The amount of consumed randomness is not fixed.
        """
        length_bits = _ceil(_log(n, 2))
        R = self.getrandbits(length_bits)
        while R >= n:
            R = self.getrandbits(length_bits)
        return (R)

    def shuffle(self, x):
        """Shuffles a list x.

        Uses the Fisher-Yates algorithm.
        Each possible permutation of x is generated with equal probability.
        """

        length_list = len(x)
        for i in reversed(range(length_list)):
            j = self.randbelow(i + 1)
            x[i], x[j] = x[j], x[i]


# ----------------------------------------------------------------------
# Create one instance, and export its methods as module-level functions.
# The functions share state across all uses.

_inst = strong_random()
load = _inst.load
size = _inst.size
isempty = _inst.isempty
printstatus = _inst.printstatus
getrandbits = _inst.getrandbits
randbelow = _inst.randbelow
shuffle = _inst.shuffle
