/*
 * 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.cryptolib.elgamal.factory;

import static org.junit.Assert.assertNotNull;

import java.math.BigInteger;

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.commons.utils.system.OperatingSystem;
import com.scytl.cryptolib.elgamal.bean.ElGamalEncryptionParameters;
import com.scytl.cryptolib.elgamal.bean.ElGamalKeyPair;
import com.scytl.cryptolib.elgamal.configuration.ConfigGroupType;
import com.scytl.cryptolib.elgamal.configuration.ElGamalPolicy;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.cryptolib.primitives.securerandom.configuration.ConfigSecureRandomAlgorithmAndProvider;

public class ElGamalFactoryTest {

    private static BigInteger _g;

    private static BigInteger _q;

    private static BigInteger _p;

    private static ZpSubgroup _group;

    private static int _numKeys;

    private static ElGamalPolicy _cryptoElGamalPolicyImpl;

    private static ElGamalFactory _cryptoElGamalFactory;

    private static ElGamalKeyPair _cryptoElGamalKeyPair;

    private static ElGamalEncryptionParameters _elGamalEncryptionParameters;

    @BeforeClass
    public static void setUp() throws GeneralCryptoLibException {

        _g = new BigInteger("2");

        _q = new BigInteger("11");

        _p = new BigInteger("23");

        _group = new ZpSubgroup(_g, _p, _q);

        _numKeys = 4;

        _cryptoElGamalPolicyImpl = getCryptoElGamalPolicy();

        _cryptoElGamalFactory =
            new ElGamalFactory(_cryptoElGamalPolicyImpl);

        _elGamalEncryptionParameters =
            new ElGamalEncryptionParameters(_p, _q, _g);

        _cryptoElGamalKeyPair =
            _cryptoElGamalFactory.createCryptoElGamalKeyPairGenerator()
                .generateKeys(_elGamalEncryptionParameters, _numKeys);
    }

    @Test
    public void givenFactoryWhenCreateKeyPairGeneratorThenExpectedNumKeys() {

        CryptoElGamalKeyPairGenerator cryptoElGamalKeyPairGenerator =
            _cryptoElGamalFactory.createCryptoElGamalKeyPairGenerator();

        assertNotNull(cryptoElGamalKeyPairGenerator);
    }

    @Test
    public void givenFactoryWhenCreateEncrypterThenOk() throws Exception {

        _cryptoElGamalFactory.createEncrypter(_cryptoElGamalKeyPair
            .getPublicKeys());
    }

    @Test
    public void givenFactoryWhenCreateDecrypterThenOk() throws Exception {

        _cryptoElGamalFactory.createDecrypter(_cryptoElGamalKeyPair
            .getPrivateKeys());
    }

    @Test
    public void givenFactoryWhenCreateReEncrypterThenOk() throws Exception {

        _cryptoElGamalFactory.createReEncrypter(_cryptoElGamalKeyPair
            .getPublicKeys());
    }

    private static ElGamalPolicy getCryptoElGamalPolicy() {

        return new ElGamalPolicy() {

            @Override
            public ConfigGroupType getGroupType() {
                return ConfigGroupType.ZP_2048_256;
            }

            @Override
            public ConfigSecureRandomAlgorithmAndProvider getSecureRandomAlgorithmAndProvider() {

                switch (OperatingSystem.current()) {

                case WINDOWS:
                    return ConfigSecureRandomAlgorithmAndProvider.PRNG_SUN_MSCAPI;
                case LINUX:
                    return ConfigSecureRandomAlgorithmAndProvider.NATIVE_PRNG_SUN;
                default:
                    throw new CryptoLibException("OS not supported");
                }
            }
        };
    }
}
