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

import java.math.BigInteger;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import com.scytl.cryptolib.mathematical.groups.impl.Exponent;
import com.scytl.products.ov.mixnet.commons.beans.Permutation;
import com.scytl.products.ov.mixnet.commons.proofs.bg.commitments.CommitmentParams;
import com.scytl.products.ov.mixnet.commons.proofs.bg.commitments.PrivateCommitment;
import com.scytl.products.ov.mixnet.commons.proofs.bg.commitments.PublicCommitment;
import com.scytl.products.ov.mixnet.commons.proofs.bg.config.ProofsGeneratorConfigurationParams;
import com.scytl.products.ov.mixnet.commons.tools.MatrixArranger;
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiation;
import com.scytl.products.ov.mixnet.proofs.bg.state.StateHarvester;
import com.scytl.products.ov.mixnet.proofs.bg.state.StateLabel;

/**
 * Class which generates the initial message.
 */
public class FirstCommitmentGenerator extends BaseCommitmentGenerator {

    private static final Logger LOG = LoggerFactory.getLogger("std");

    private final int m;

    private final int n;

    private final Permutation permutation;

    private final BigInteger order;

    public FirstCommitmentGenerator(final ProofsGeneratorConfigurationParams config, final Permutation permutation,
            final CommitmentParams comParams,
            final PrivateAndPublicCommitmentsGenerator privateAndPublicCommitmentsGenerator,
            final MultiExponentiation limMultiExpo, final int concurrencyLevel) {

        super(config.getMatrixDimensions().getNumberOfRows(), config.getZpGroupParams().getQ(), comParams,
            privateAndPublicCommitmentsGenerator, limMultiExpo, concurrencyLevel);
        this.order = config.getZpGroupParams().getQ();
        this.m = config.getMatrixDimensions().getNumberOfRows();
        this.n = config.getMatrixDimensions().getNumberOfColumns();
        this.permutation = permutation;
    }

    /**
     * Decomposes the given permutation into a matrix of {@code m} rows and {@code n} columns.
     */
    @Override
    protected Exponent[][] initExponents(final StateHarvester harvester) {
        return MatrixArranger.transformPermutationToExponentMatrix(permutation, order, m, n);
    }

    @Override
    protected void publishCommitments(final PrivateCommitment[] privateCommitments,
            final PublicCommitment[] publicCommitments, final StateHarvester harvester) {

        LOG.info("Publishing first commitment");

        harvester.collect(Produced.PUBLIC_COMMITS, publicCommitments);
        harvester.collect(Produced.PRIVATE_COMMITS, privateCommitments);
    }

    public enum Produced implements StateLabel {
        PUBLIC_COMMITS, PRIVATE_COMMITS
    }

}
