/*
 * 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.api.primitives;

import java.io.InputStream;
import java.security.MessageDigest;
import java.util.List;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.derivation.cryptoapi.CryptoAPIKDFDeriver;
import com.scytl.cryptolib.derivation.cryptoapi.CryptoAPIPBKDFDeriver;
import com.scytl.cryptolib.ffc.cryptoapi.FFCEngine;
import com.scytl.cryptolib.securerandom.cryptoapi.CryptoAPIRandomBytes;
import com.scytl.cryptolib.securerandom.cryptoapi.CryptoAPIRandomInteger;
import com.scytl.cryptolib.securerandom.cryptoapi.CryptoAPIRandomString;

/**
 * An API for creating Random data, hashing and key deriving.
 */
public interface PrimitivesServiceAPI {

    /**
     * Provides a random bytes generator.
     * 
     * @return a {@link CryptoAPIRandomBytes}.
     */
    CryptoAPIRandomBytes getCryptoRandomBytes();

    /**
     * Provides a random integer generator.
     * 
     * @return a {@link CryptoAPIRandomInteger}.
     */
    CryptoAPIRandomInteger getCryptoRandomInteger();

    /**
     * Provides a {@link CryptoAPIRandomString} already configured to return
     * random strings according the RFC 4648 base32 alphabet.
     * 
     * @return a {@link CryptoAPIRandomString}
     */
    CryptoAPIRandomString get32CharAlphabetCryptoRandomString();

    /**
     * Provides a {@link CryptoAPIRandomString} already configured to return
     * random strings according the RFC 4648 base64 alphabet.
     * 
     * @return a {@link CryptoAPIRandomString}
     */
    CryptoAPIRandomString get64CharAlphabetCryptoRandomString();

    /**
     * Provides a KDF key deriver.
     * 
     * @return a {@link CryptoAPIKDFDeriver}.
     */
    CryptoAPIKDFDeriver getKDFDeriver();

    /**
     * Provides a PBKDF key deriver.
     * 
     * @return a {@link CryptoAPIPBKDFDeriver}.
     */
    CryptoAPIPBKDFDeriver getPBKDFDeriver();

    /**
     * Generates a hash for the given data.
     *
     * @param data
     *            the input data for the hash.
     * @return The byte[] representing the generated hash.
     * @throws GeneralCryptoLibException
     *             if {@code data[]} is not correct.
     */
    byte[] getHash(final byte[] data) throws GeneralCryptoLibException;

    /**
     * Generates a hash for the data that is readable from an input stream.
     * 
     * @param in
     *            the input stream from which data should be read.
     * @return the byte[] representing the generated hash.
     * @throws GeneralCryptoLibException
     *             if there are any problems reading data from {@code in}.
     */
    byte[] getHash(final InputStream in) throws GeneralCryptoLibException;

    /**
     * Randomly permutes the elements of the given list.
     * 
     * @param list
     *            the list to be permuted.
     * @throws GeneralCryptoLibException
     *             if the list is null, empty or contains one or more null
     *             elements.
     */
    void shuffle(List<?> list) throws GeneralCryptoLibException;

    /**
     * Returns a {@link FFCEngine} instance.
     * 
     * @return a {@link FFCEngine} instance.
     */
    FFCEngine getFFCEngine();

    /**
     * Method for returning a raw {@link MessageDigest} with the 
     * appropriate policies set for working on more low-level functionalities.
     * @return The raw {@link MessageDigest}.
     */
	MessageDigest getRawMessageDigest();
}
