/*
 * 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.products.ov.mixnet.commons.proofs.bg.commitments;

import static org.junit.Assert.assertTrue;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.mathematical.groups.impl.Exponent;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.products.ov.mixnet.commons.tools.ExponentTools;
import com.scytl.products.ov.mixnet.commons.tools.GroupTools;
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiation;
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiationImpl;

public class PrivateCommitmentTest {

    private int _n;

    private Exponent[] _exponents;

    private CommitmentParams comParams;

    private Exponent _randomExponent;

    private MultiExponentiation limMultiExpo;

    @Before
    public void setUp() {

        final BigInteger p = new BigInteger("15294034768093677312256663166625633354362303");
        final BigInteger q = new BigInteger("7647017384046838656128331583312816677181151");

        ZpSubgroup zp = GroupTools.createGroupWithRandomGenerator(p, q);

        _n = 10;

        _exponents = ExponentTools.getVectorRandomExponent(_n, q);

        comParams = new CommitmentParams(zp, _n);

        _randomExponent = ExponentTools.getRandomExponent(q);

        limMultiExpo = MultiExponentiationImpl.getInstance();

    }

    @Test
    public void generate_correctly_the_commitment_for_N_CPUs() {

        try {

            for (int cpu = 1; cpu < Runtime.getRuntime().availableProcessors(); cpu++) {

                PrivateCommitment _sut =
                    new PrivateCommitment(_exponents, _randomExponent, comParams, limMultiExpo);

                final PublicCommitment publicCommitment = _sut.makePublicCommitment();

                assertTrue(publicCommitment != null);

                final ZpGroupElement[] base = comParams.getG();
                final Exponent[] exponents = _sut.getM();

                final List<ZpGroupElement> list = new ArrayList<>();

                for (int i = 0; i < base.length; i++) {
                    list.add(base[i].exponentiate(exponents[i]));
                }

                ZpGroupElement element = comParams.getH().exponentiate(_randomExponent);

                for (ZpGroupElement aList : list) {
                    element = element.multiply(aList);
                }

                assertTrue(publicCommitment.getElement().equals(element));
            }

        } catch (GeneralCryptoLibException ex) {
            throw new CryptoLibException(ex);
        }
    }
}
