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

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.elgamal.bean.CiphertextImpl;
import com.scytl.cryptolib.elgamal.cryptoapi.Ciphertext;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.ov.mixing.commons.exceptions.InvalidInputException;
import com.scytl.ov.mixing.commons.tools.GroupTools;

public class ElGamalEncryptedBallotEntryParserTest {

    private static ElGamalEncryptedBallotEntryParser target;

    private static CiphertextImpl expectedEncryptedBallot;

    private static String[] stringArray;

    @BeforeClass
    public static void setUp() {

        try {

            final BigInteger p = new BigInteger("15294034768093677312256663166625633354362303");
            final BigInteger q = new BigInteger("7647017384046838656128331583312816677181151");
            final ZpSubgroup zpGroup = GroupTools.createGroupWithRandomGenerator(p, q);

            target = new ElGamalEncryptedBallotEntryParser(zpGroup);

            final String _gammaAsString = "4012556967239296284125919604329103854893595";
            final String _phi1AsString = "6054959594806155309765068576952771674747761";
            final String _phi2AsString = "11583975953794885768215634543368899452667420";

            stringArray = new String[3];
            stringArray[0] = _gammaAsString;
            stringArray[1] = _phi1AsString;
            stringArray[2] = _phi2AsString;

            final List<ZpGroupElement> elements = new ArrayList<>();
            elements.add(new ZpGroupElement(new BigInteger(_gammaAsString), p, q));
            elements.add(new ZpGroupElement(new BigInteger(_phi1AsString), p, q));
            elements.add(new ZpGroupElement(new BigInteger(_phi2AsString), p, q));

            expectedEncryptedBallot = new CiphertextImpl(elements.get(0), elements.subList(1, elements.size()));

        } catch (GeneralCryptoLibException e) {
            throw new CryptoLibException(e);
        }
    }

    @Test(expected = InvalidInputException.class)
    public void givenNullWhenParseEntryThenException() {

        final String[] args = null;
        target.parseEntry(args);
    }

    @Test(expected = InvalidInputException.class)
    public void givenEmptyArrayWhenParseEntryThenException() {

        final String[] args = new String[0];
        target.parseEntry(args);
    }

    @Test
    public void givenStringArrayWhenParseEntryThenOk() throws GeneralCryptoLibException {

        final Ciphertext parsedEncryptedBallot = target.parseEntry(stringArray);

        final String errorMsg = "The parsed ballot did was not equal to the expected ballot";
        assertEquals(errorMsg, serializeBallots(expectedEncryptedBallot), serializeBallots(parsedEncryptedBallot));
    }

    private String serializeBallots(Ciphertext ciphertextImpl) throws GeneralCryptoLibException {
        StringBuffer sb = new StringBuffer();
        sb.append(ciphertextImpl.getGamma().toJson());
        List<ZpGroupElement> phis = ciphertextImpl.getPhis();
        for (ZpGroupElement zpGroupElement : phis) {
            sb.append(zpGroupElement.toJson());
        }
        return sb.toString();
    }
}
