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

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.api.primitives.PrimitivesServiceAPI;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.products.ov.commons.beans.validation.CryptographicOperationException;

/**
 * Convert partial choice codes into long codes
 */
@Stateless
public class LongCodesService {

    // The service that will be used to calculate the long codes
    @Inject
    private PrimitivesServiceAPI primitivesService;

    /**
     * Calculates the Long codes regarding the encrypted choice codes received.
     *
     * @param eeid
     *            - election event identifier.
     * @param verificationCardId
     *            - verification card id
     * @param partialCodeList
     *            - the list of partial codes used to calculate long codes
     * @param correctnessIds
     *            - the correctness ids
     * @return
     * @throws CryptographicOperationException
     */
    public List<byte[]> calculateLongCodes(String eeid, String verificationCardId, List<ZpGroupElement> partialCodeList,
            List<String[]> correctnessIds) throws CryptographicOperationException {
        int size = partialCodeList.size();
        List<byte[]> longCodes = new ArrayList<>(size);

        try {
            int index = 0;
            StringBuffer longChoiceCodeData = new StringBuffer();
            for (ZpGroupElement partialCode : partialCodeList) {
                longChoiceCodeData.append(partialCode.getValue());
                longChoiceCodeData.append(verificationCardId);
                longChoiceCodeData.append(eeid);
                for (String correctnessId : correctnessIds.get(index)) {
                    longChoiceCodeData.append(correctnessId);
                }

                byte[] longChoiceCodeDataBytes = longChoiceCodeData.toString().getBytes(StandardCharsets.UTF_8);
                byte[] longChoiceCode = primitivesService.getHash(longChoiceCodeDataBytes);
                longCodes.add(longChoiceCode);

                // Clear the buffer
                longChoiceCodeData.setLength(0);

                index++;
            }

            return longCodes;
        } catch (GeneralCryptoLibException e) {
            throw new CryptographicOperationException("Error calculating long choice codes:", e);
        }
    }
}
