/*
 * 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.ov.mixing.commons.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.ArrayList;

import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.ov.mixing.commons.proofs.bg.commitments.CommitmentParams;

public class CommitmentParamsReader extends SerializedDataReader {

    /**
     * Reads a set of commitment parameters from a file. Note: a set of commitment parameters contains a "h" value and
     * an array of "g" values. Additionally, a set of encryption parameters are stored with the commitment parameters.
     * Note: this methods assumes that the file will contain the following lines:
     * <ul>
     * <li>P parameter</li>
     * <li>Q parameter</li>
     * <li>G parameter</li>
     * <li>h</li>
     * <li>g[0]</li>
     * <li>g[1]</li>
     * <li>g[2]</li>
     * <li>...</li>
     * <li>g[N]</li>
     * </ul>
     * For example, if the commitment parameters contains a "g" array with 64 elements, then the total number of lines
     * in the file should be 68 (3 "encryption parameters" lines + 1 "h" line + 64 "g" lines).
     *
     * @param zpGroup
     *            the group to which the commitment parameters belong.
     * @param commitmentFile
     *            the path of the file containing a set of commitment parameters.
     * @return the reconstructed commitment parameters.
     * @throws IOException
     */
    public static CommitmentParams readCommitmentParamsFromStream(final ZpSubgroup zpGroup,
            final InputStream commitment) throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(commitment))) {
            // read the group information
            final String pAsString = readLineAndConfirmNotNull(reader);
            final String qAsString = readLineAndConfirmNotNull(reader);
            // read g to have the correct reader state
            readLineAndConfirmNotNull(reader);

            // read the commitment values
            final String hAsString = readLineAndConfirmNotNull(reader);

            BigInteger p = new BigInteger(pAsString);
            BigInteger q = new BigInteger(qAsString);

            final ZpGroupElement h = new ZpGroupElement(new BigInteger(hAsString), p, q);

            // read each of the remaining lines in the file, and assign them to
            // the commitments array
            final ArrayList<ZpGroupElement> g = new ArrayList<>();
            String line;
            while ((line = reader.readLine()) != null) {
                g.add(new ZpGroupElement(new BigInteger(line), p, q));
            }

            ZpGroupElement[] commitmentGenerators = g.toArray(new ZpGroupElement[g.size()]);
            return new CommitmentParams(zpGroup, h, commitmentGenerators);
            
        } catch (GeneralCryptoLibException e) {
            throw new CryptoLibException(e);
        }
    }
}
