/*
 * 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.proofs.bg.multiexp.reduction;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

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

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.mathematical.groups.impl.Exponent;
import com.scytl.ov.mixing.commons.beans.proofs.MultiExponentiationReductionAnswer;
import com.scytl.ov.mixing.commons.beans.proofs.MultiExponentiationReductionInitialMessage;
import com.scytl.ov.mixing.commons.homomorphic.impl.GjosteenElGamalRandomness;
import com.scytl.ov.mixing.commons.proofs.bg.commitments.PrivateCommitment;
import com.scytl.ov.mixing.commons.proofs.bg.commitments.PublicCommitment;
import com.scytl.ov.mixing.commons.tools.CommitmentTools;
import com.scytl.ov.mixing.commons.tools.ExponentTools;
import com.scytl.ov.mixing.commons.tools.MatrixArranger;
import com.scytl.ov.mixing.proofs.bg.BasicProofsInitializer;
import com.scytl.ov.mixing.proofs.bg.multiexp.MultiExponentiationProofGenerator;
import com.scytl.ov.mixing.proofs.bg.multiexp.basic.BasicProofGenerator;
import com.scytl.ov.mixing.proofs.bg.multiexp.basic.ParallelBasicProofGenerator;
import com.scytl.ov.mixing.proofs.bg.shuffle.SecondCommitmentGenerator;
import com.scytl.ov.mixing.proofs.bg.state.CommonStateLabels;
import com.scytl.ov.mixing.proofs.bg.state.MapBasedHarvester;
import com.scytl.ov.mixing.proofs.bg.state.StateHarvester;

@Ignore
public class ParallelReductionProofGeneratorTest extends BasicProofsInitializer {

    private final StateHarvester _harvester = new MapBasedHarvester();

    private ParallelReductionProofGenerator _sut;

    @Before
    public void initHarvester() throws GeneralCryptoLibException {

        _harvester.collect(CommonStateLabels.REDUCT_ITERATIONS_LEFT, 1);
        _harvester.collect(CommonStateLabels.CIPHERTEXTS, getMockedReEncryptedCiphertexts());

        final Exponent[][] exponents =
            MatrixArranger.transformPermutationToExponentMatrix(getMockedPermutation(), q, m, n);
        final PrivateCommitment[] privateCommitmentsB = getMockedPrivateCommitments(exponents);
        final PublicCommitment[] publicCommitmentsB = CommitmentTools.makePublic(privateCommitmentsB);
        _harvester.collect(SecondCommitmentGenerator.Produced.PRIVATE_COMMITS, privateCommitmentsB);
        _harvester.collect(SecondCommitmentGenerator.Produced.PUBLIC_COMMITS, publicCommitmentsB);

        _harvester.collect(MultiExponentiationProofGenerator.Produced.CALCULATED_RANDOM_EXPONENT,
            new GjosteenElGamalRandomness(ExponentTools.getRandomExponent(q)));
    }

    @Test
    public void generate_the_reduction_proof_correctly()
            throws GeneralCryptoLibException {

        final BasicProofGenerator basicProofGenerator =
            new ParallelBasicProofGenerator(config, commitmentParams, limMultiExpo, computeAllE, concurrencyLevel);

        _sut = new ParallelReductionProofGenerator(config, commitmentParams.getCommitmentLength(), basicProofGenerator,
            commitmentParams, computeAllE, limMultiExpo, concurrencyLevel);

        _sut.generate(_harvester);

        final MultiExponentiationReductionInitialMessage multiExponentiationReductionInitialMessage =
            _harvester.offer(ReductionProofGenerator.Produced.REDUCT_MULTIEXP_INIT_MSG,
                MultiExponentiationReductionInitialMessage.class);

        assertThat(multiExponentiationReductionInitialMessage != null, is(true));

        final MultiExponentiationReductionAnswer multiExponentiationReductionAnswer = _harvester
            .offer(ReductionProofGenerator.Produced.REDUCT_MULTIEXP_ANSWER, MultiExponentiationReductionAnswer.class);

        assertThat(multiExponentiationReductionAnswer != null, is(true));

    }
}
