/*
 * 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.commons.concurrent.processor;

import com.scytl.cryptolib.mathematical.groups.impl.Exponent;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.ov.mixing.commons.concurrent.ParallelProcessTask;
import com.scytl.ov.mixing.commons.proofs.bg.commitments.CommitmentParams;
import com.scytl.ov.mixing.commons.tools.LoopTools.Range;
import com.scytl.ov.mixing.commons.tools.MultiExponentiation;

/**
 * Base case to be parallelized using {@code LoopParallelizer Task}
 */
public class LimMultiExpoConcurrentCalculatorProcess implements ParallelProcessTask<ZpGroupElement> {

    private final ZpGroupElement[] base;

    private final Exponent[] exponents;

    private final CommitmentParams params;

    private final MultiExponentiation multiExponentiation;

    public LimMultiExpoConcurrentCalculatorProcess(final ZpGroupElement[] base, final Exponent[] exponents,
            final CommitmentParams params, final MultiExponentiation multiExponentiation) {

        this.base = base;
        this.exponents = exponents;
        this.params = params;
        this.multiExponentiation = multiExponentiation;
    }

    /**
     * @see com.scytl.products.ov.mixnet.commons.concurrent.ParallelProcessAction#run(com.scytl.products.ov.mixnet
     *      .commons.tools.LoopTools.Range)
     */
    @Override
    public ZpGroupElement run(final Range range) {
        final int lengthIteration = range.getEnd() - range.getStart();

        final ZpGroupElement[] trimmedBase = new ZpGroupElement[lengthIteration];

        final Exponent[] trimmedExponent = new Exponent[lengthIteration];

        System.arraycopy(base, range.getStart(), trimmedBase, 0, lengthIteration);

        System.arraycopy(exponents, range.getStart(), trimmedExponent, 0, lengthIteration);

        ZpSubgroup zpGroup = params.getGroup();

        return multiExponentiation.computeMultiExpo(zpGroup, trimmedBase, trimmedExponent);
    }
}
