package meerkat.util;

import com.google.protobuf.ByteString;
import meerkat.crypto.DigitalSignature;
import meerkat.protobuf.BulletinBoardApi.*;
import com.google.protobuf.Timestamp;

import java.math.BigInteger;
import java.security.SignatureException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * Created by Arbel Deutsch Peled on 21-Feb-16.
 * This class contains methods used to generate random Bulletin Board Messages
 */
public class BulletinBoardMessageGenerator {

    private Random random;

    public BulletinBoardMessageGenerator(Random random) {
        this.random = random;
    }

    private byte randomByte(){
        return (byte) random.nextInt();
    }

    private byte[] randomBytes(int length) {

        byte[] result = new byte[length];

        for (int i = 0; i < length; i++) {
            result[i] = randomByte();
        }

        return result;
    }

    private String randomString(){
        return new BigInteger(130, random).toString(32);
    }

    private List<String> randomStrings(int length) {

        List<String> result = new LinkedList<>();

        for (int i = 0; i < length; i++) {
            result.add(randomString());
        }

        return result;

    }

    /**
     * Generates a complete instance of a BulletinBoardMessage
     * @param signers contains the (possibly multiple) credentials required to sign the message
     * @param timestamp contains the time used in the message
     * @param dataSize is the length of the data contained in the message
     * @param tagNumber is the number of tags to generate
     * @param tags is a list of initial tags (on top of which more will be added according to the method input)
     * @return a random, signed Bulletin Board Message containing random data and tags and the given timestamp
     */
    public BulletinBoardMessage generateRandomMessage(DigitalSignature[] signers, Timestamp timestamp, int dataSize, int tagNumber, List<String> tags)
            throws SignatureException{

        // Generate random data.





        UnsignedBulletinBoardMessage unsignedMessage =
                UnsignedBulletinBoardMessage.newBuilder()
                        .setData(ByteString.copyFrom(randomBytes(dataSize)))
                        .setTimestamp(timestamp)
                        .addAllTag(tags)
                        .addAllTag(randomStrings(tagNumber))
                        .build();

        BulletinBoardMessage.Builder messageBuilder =
                BulletinBoardMessage.newBuilder()
                        .setMsg(unsignedMessage);

        for (int i = 0 ; i < signers.length ; i++) {
            signers[i].updateContent(unsignedMessage);
            messageBuilder.addSig(signers[i].sign());
        }

        return messageBuilder.build();

    }

    /**
     * Generates a complete instance of a BulletinBoardMessage
     * @param signers contains the (possibly multiple) credentials required to sign the message
     * @param timestamp contains the time used in the message
     * @param dataSize is the length of the data contained in the message
     * @param tagNumber is the number of tags to generate
     * @return a random, signed Bulletin Board Message containing random data and tags and the given timestamp
     */

    public BulletinBoardMessage generateRandomMessage(DigitalSignature[] signers, Timestamp timestamp, int dataSize, int tagNumber)
            throws SignatureException {

        List<String> tags = new LinkedList<>();
        return generateRandomMessage(signers, timestamp, dataSize, tagNumber, tags);

    }

    /**
     * Generates a complete instance of a BulletinBoardMessage
     * @param signers contains the (possibly multiple) credentials required to sign the message
     * @param dataSize is the length of the data contained in the message
     * @param tagNumber is the number of tags to generate
     * @return a random, signed Bulletin Board Message containing random data, tags and timestamp
     */
    public BulletinBoardMessage generateRandomMessage(DigitalSignature[] signers, int dataSize, int tagNumber)
            throws SignatureException {

        Timestamp timestamp = Timestamp.newBuilder()
                .setSeconds(random.nextLong())
                .setNanos(random.nextInt())
                .build();

        return generateRandomMessage(signers, timestamp, dataSize, tagNumber);

    }

}
