package meerkat.mixer.proofs.concrete;

import meerkat.crypto.concrete.Util;
import meerkat.mixer.proofs.Concatenator;
import meerkat.protobuf.Mixing;

import java.math.BigInteger;

/**
 * Created by talm on 12/01/17.
 */
public class ProtobufConcatenators {
    public final static ConcatAnd1 concatAnd1 = new ConcatAnd1();
    public final static ConcatAnd2 concatAnd2 = new ConcatAnd2();
    public final static ConcatMix1 concatMix1 = new ConcatMix1();
    public final static ConcatMix2 concatMix2 = new ConcatMix2();
    public final static ConcatNIZK concatNIZK = new ConcatNIZK();

    public static class ConcatAnd1 implements Concatenator.Pair<Mixing.Mix2Proof.AndProof.FirstMessage,Mixing.Mix2Proof.DlogProof.FirstMessage,Mixing.Mix2Proof.DlogProof.FirstMessage> {
        @Override
        public Mixing.Mix2Proof.AndProof.FirstMessage concatenate(Mixing.Mix2Proof.DlogProof.FirstMessage msg1, Mixing.Mix2Proof.DlogProof.FirstMessage msg2) {
            return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder()
                    .setClause0(msg1)
                    .setClause1(msg2)
                    .build();
        }

        @Override
        public Mixing.Mix2Proof.DlogProof.FirstMessage getMsg1(Mixing.Mix2Proof.AndProof.FirstMessage msg) { return msg.getClause0(); }

        @Override
        public Mixing.Mix2Proof.DlogProof.FirstMessage getMsg2(Mixing.Mix2Proof.AndProof.FirstMessage msg) { return msg.getClause1(); }
    }

    public static class ConcatAnd2 implements Concatenator.Pair<Mixing.Mix2Proof.AndProof.FinalMessage,Mixing.Mix2Proof.DlogProof.FinalMessage,Mixing.Mix2Proof.DlogProof.FinalMessage> {
        @Override
        public Mixing.Mix2Proof.AndProof.FinalMessage concatenate(Mixing.Mix2Proof.DlogProof.FinalMessage msg1, Mixing.Mix2Proof.DlogProof.FinalMessage msg2) {
            return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder()
                    .setClause0(msg1)
                    .setClause1(msg2)
                    .build();
        }

        @Override
        public Mixing.Mix2Proof.DlogProof.FinalMessage getMsg1(Mixing.Mix2Proof.AndProof.FinalMessage msg) { return msg.getClause0(); }

        @Override
        public Mixing.Mix2Proof.DlogProof.FinalMessage getMsg2(Mixing.Mix2Proof.AndProof.FinalMessage msg) { return msg.getClause1(); }
    }

    public static class ConcatMix1 implements Concatenator.Pair<Mixing.Mix2Proof.FirstMessage,Mixing.Mix2Proof.AndProof.FirstMessage,Mixing.Mix2Proof.AndProof.FirstMessage> {
        @Override
        public Mixing.Mix2Proof.FirstMessage concatenate(Mixing.Mix2Proof.AndProof.FirstMessage msg1, Mixing.Mix2Proof.AndProof.FirstMessage msg2) {
            return Mixing.Mix2Proof.FirstMessage.newBuilder()
                    .setClause0(msg1)
                    .setClause1(msg2)
                    .build();
        }

        @Override
        public Mixing.Mix2Proof.AndProof.FirstMessage getMsg1(Mixing.Mix2Proof.FirstMessage msg) { return msg.getClause0(); }

        @Override
        public Mixing.Mix2Proof.AndProof.FirstMessage getMsg2(Mixing.Mix2Proof.FirstMessage msg)  { return msg.getClause1(); }
    }

    public static class ConcatMix2 implements Concatenator.Triplet<Mixing.Mix2Proof.FinalMessage,BigInteger,Mixing.Mix2Proof.AndProof.FinalMessage,Mixing.Mix2Proof.AndProof.FinalMessage>  {
        @Override
        public Mixing.Mix2Proof.FinalMessage concatenate(BigInteger msg1, Mixing.Mix2Proof.AndProof.FinalMessage msg2, Mixing.Mix2Proof.AndProof.FinalMessage msg3) {
            return Mixing.Mix2Proof.FinalMessage.newBuilder()
                    .setC0(Util.encodeBigInteger(msg1))
                    .setClause0(msg2)
                    .setClause1(msg3)
                    .build();
        }

        @Override
        public BigInteger getMsg1of3(Mixing.Mix2Proof.FinalMessage msg) { return Util.decodeBigInteger(msg.getC0()); }

        @Override
        public Mixing.Mix2Proof.AndProof.FinalMessage getMsg2of3(Mixing.Mix2Proof.FinalMessage msg) { return msg.getClause0(); }

        @Override
        public Mixing.Mix2Proof.AndProof.FinalMessage getMsg3of3(Mixing.Mix2Proof.FinalMessage msg) { return msg.getClause1(); }
    }


    public static class ConcatNIZK implements Concatenator.Pair<Mixing.Mix2Proof, Mixing.Mix2Proof.FirstMessage,Mixing.Mix2Proof.FinalMessage> {

        @Override
        public Mixing.Mix2Proof concatenate(Mixing.Mix2Proof.FirstMessage msg1, Mixing.Mix2Proof.FinalMessage msg2) {
            return Mixing.Mix2Proof.newBuilder()
                    .setFirstMessage(msg1)
                    .setFinalMessage(msg2)
                    .build();
        }

        @Override
        public Mixing.Mix2Proof.FirstMessage getMsg1(Mixing.Mix2Proof msg) {
            return msg.getFirstMessage();
        }

        @Override
        public Mixing.Mix2Proof.FinalMessage getMsg2(Mixing.Mix2Proof msg) {
            return msg.getFinalMessage();
        }
    }
}
