/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.primitives.ffc;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Fake implementation of {@link PseudoRandom}.
 */
class FakePseudoRandom implements PseudoRandom {
    private final MessageDigest digest;

    private BigInteger seed;

    private FakePseudoRandom(MessageDigest digest, BigInteger seed) {
        this.digest = digest;
        this.seed = seed;
    }

    /**
     * Creates a new instance from seed.
     * 
     * @param seed
     *            the seed
     * @return the instance.
     */
    public static FakePseudoRandom newInstance(BigInteger seed) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("Failed to create instance.",
                e);
        }
        return new FakePseudoRandom(digest, seed);
    }

    /**
     * Creates a new instance from some seed.
     * 
     * @param seedLength
     *            the seed length
     * @return the instance.
     */
    public static FakePseudoRandom newInstance(int seedLength) {
        return newInstance(BigInteger.ONE.shiftLeft(seedLength - 1));
    }

    @Override
    public BigInteger next() {
        byte[] bytes = seed.toByteArray();
        seed = seed.add(BigInteger.ONE);
        byte[] hash = digest.digest(bytes);
        return new BigInteger(1, hash);
    }

    @Override
    public BigInteger next(int length) {
        int outlen = digest.getDigestLength();
        int iterations = (length + outlen - 1) / outlen;
        BigInteger value = BigInteger.ZERO;
        for (int i = 0; i < iterations; i++) {
            value = value.add(next().shiftLeft(i * outlen));
        }
        return value;
    }

    @Override
    public BigInteger seed() {
        return seed;
    }

}
