package meerkat.mixer.proofs.concrete;

import meerkat.mixer.proofs.SigmaProtocol;
import meerkat.mixer.proofs.SigmaProtocolTest;
import meerkat.mixer.proofs.generic.SigmaProtocolOr2;
import meerkat.protobuf.Mixing;
import org.factcenter.qilin.util.Pair;

import java.math.BigInteger;

/**
 * Created by talm on 14/01/17.
 */
public class DlogOrStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> {
    final DlogStatementSchnorrSigmaTest dlogtest;

    final Statements.AndStatement[] statements = new Statements.AndStatement[2];
    Statements.AndStatementWitness w;
    int trueStatementIndex;


    public DlogOrStatementSigmaTest() {
        this.dlogtest = new DlogStatementSchnorrSigmaTest();
    }

    @Override
    protected void generateRandomTrueStatement() {
        trueStatementIndex = rand.nextInt(2);
        Pair<Statements.DlogStatement, Statements.DlogStatementWitness> s1w1 = dlogtest.returnRandomTrueStatement();
        Pair<Statements.DlogStatement, Statements.DlogStatementWitness> s2w2 = dlogtest.returnRandomTrueStatement();
        Statements.AndStatement trueStatement = dlogtest.statementGenerator.new AndStatement(s1w1.a, s2w2.a);
        w = dlogtest.statementGenerator.new AndStatementWitness(s1w1.b, s2w2.b);
        statements[trueStatementIndex] = trueStatement;

        Statements.DlogStatement f1 = dlogtest.returnRandomFalseStatement();
        Statements.DlogStatement f2 = dlogtest.returnRandomFalseStatement();

        Statements.AndStatement falseStatement = dlogtest.statementGenerator.new AndStatement(f1, f2);

        statements[1 - trueStatementIndex] = falseStatement;
    }

    @Override
    protected void generateRandomFalseStatement() {
        Statements.DlogStatement f1 = dlogtest.returnRandomFalseStatement();
        Statements.DlogStatement f2 = dlogtest.returnRandomFalseStatement();

        statements[0] = dlogtest.statementGenerator.new AndStatement(f1, f2);

        f1 = dlogtest.returnRandomFalseStatement();
        f2 = dlogtest.returnRandomFalseStatement();
        statements[1] = dlogtest.statementGenerator.new AndStatement(f1, f2);
    }

    @Override
    protected SigmaProtocol.Prover<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewProver() {
        SigmaProtocol.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andProver = new DlogConjunction.Prover(dlogtest.encryptor, rand, statements[trueStatementIndex], w);
        SigmaProtocol.Simulator<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andSimulator = new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1 - trueStatementIndex]);

        Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
        return new SigmaProtocolOr2.Prover<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
                gen, andProver, andSimulator, trueStatementIndex);
    }

    @Override
    protected SigmaProtocol.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage>  getNewVerifier() {
        Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
        return new SigmaProtocolOr2.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage,
                Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
                gen, new DlogConjunction.Verifier(dlogtest.encryptor, statements[0]), new DlogConjunction.Verifier(dlogtest.encryptor, statements[1]));
    }

    @Override
    protected SigmaProtocol.Simulator<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage>  getNewSimulator() {

        Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
        return new SigmaProtocolOr2.Simulator<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage,
                Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
                gen, new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[0]),
                new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1]));
    }

    @Override
    protected BigInteger getChallengeModulus() {
        return dlogtest.getChallengeModulus();
    }
}
