/*
 * 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.batches;

import java.util.List;

import com.scytl.cryptolib.api.primitives.PrimitivesServiceAPI;
import com.scytl.cryptolib.elgamal.bean.ElGamalPrivateKey;
import com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey;
import com.scytl.cryptolib.elgamal.cryptoapi.Ciphertext;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.products.ov.mixnet.BGMixer;
import com.scytl.products.ov.mixnet.commons.ballots.ElGamalEncryptedBallots;
import com.scytl.products.ov.mixnet.commons.configuration.BGParams;
import com.scytl.products.ov.mixnet.commons.configuration.locations.LocationsProvider;
import com.scytl.products.ov.mixnet.commons.homomorphic.Randomness;
import com.scytl.products.ov.mixnet.commons.homomorphic.impl.GjosteenElGamal;
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiation;
import com.scytl.products.ov.mixnet.proofs.bg.multiexp.ParallelComputeAllE;

/**
 * This class creates mixing batches which share common business data such as the encryption parameters, the public key,
 * I/O configuration, among others...
 */
public class MixingBatchFactory {

    private final BGMixer mixer;

    private final ZpSubgroup zpGroup;

    private final GjosteenElGamal gjosteenElGamal;

    private final int concurrencyLevel;

    private final ElGamalPublicKey publicKey;

    private final LocationsProvider locationsProvider;

    private final MultiExponentiation multiExponentiation;

    private final ParallelComputeAllE parallelComputeAllE;

    private final ElGamalPrivateKey ballotDecryptionKey;

    private PrimitivesServiceAPI primitivesService;

    private MixingBatchFactory(final BGMixer mixer, final ZpSubgroup zpGroup, final GjosteenElGamal gjosteenElGamal,
            final int concurrencyLevel, final ElGamalPublicKey publicKey,
            final ElGamalPrivateKey ballotDecryptionKey, final LocationsProvider locationsProvider,
            final MultiExponentiation multiExponentiation, final ParallelComputeAllE parallelComputeAllE,
            PrimitivesServiceAPI primitivesService) {

        this.mixer = mixer;
        this.zpGroup = zpGroup;
        this.gjosteenElGamal = gjosteenElGamal;
        this.concurrencyLevel = concurrencyLevel;
        this.publicKey = publicKey;
        this.ballotDecryptionKey = ballotDecryptionKey;
        this.locationsProvider = locationsProvider;
        this.multiExponentiation = multiExponentiation;
        this.parallelComputeAllE = parallelComputeAllE;
        this.primitivesService = primitivesService;
    }

    public static MixingBatchFactory aNew(final BGMixer mixer, final ZpSubgroup zpGroup,
            final GjosteenElGamal gjosteenElGamal, int concurrencyLevel,
            final ElGamalPublicKey publicKey, final ElGamalPrivateKey ballotDecryptionKey,
            final LocationsProvider locationsProvider, final MultiExponentiation multiExponentiation,
            final ParallelComputeAllE parallelComputeAllE, PrimitivesServiceAPI primitivesService) {

        return new MixingBatchFactory(mixer, zpGroup, gjosteenElGamal, concurrencyLevel, publicKey,
            ballotDecryptionKey, locationsProvider, multiExponentiation, parallelComputeAllE, primitivesService);
    }

    public MixingBatch create(final int partitionSize, final ElGamalEncryptedBallots batchElGamalEncryptedBallots,
            final Integer batchNum, final int offset, final BGParams bGParams, final int i,
            final Randomness[] batchRandomness, final List<Ciphertext> batchPreComputations) {

        return new MixingBatch(partitionSize, mixer, batchElGamalEncryptedBallots, batchNum, offset, bGParams,
            zpGroup, gjosteenElGamal, concurrencyLevel, i, publicKey, ballotDecryptionKey, locationsProvider,
            multiExponentiation, parallelComputeAllE, batchRandomness, batchPreComputations, primitivesService);
    }
}
