/*
 * 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.certificates.factory.builders;

import static org.junit.Assert.assertNotNull;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;
import com.scytl.cryptolib.certificates.bean.ValidityDates;
import com.scytl.cryptolib.certificates.bean.X509DistinguishedName;
import com.scytl.cryptolib.certificates.configuration.ConfigX509CertificateAlgorithmAndProvider;
import com.scytl.cryptolib.primitives.securerandom.factory.CryptoRandomInteger;
import com.scytl.cryptolib.primitives.securerandom.factory.CryptoRandomString;
import com.scytl.cryptolib.primitives.service.PrimitivesService;

public class BouncyCastleX509CertificateBuilderTest {

    private final ConfigX509CertificateAlgorithmAndProvider _configDefault =
        ConfigX509CertificateAlgorithmAndProvider.SHA256_WITH_RSA_DEFAULT;

    private final ConfigX509CertificateAlgorithmAndProvider _configBC =
        ConfigX509CertificateAlgorithmAndProvider.SHA256_WITH_RSA_BC;

    private static PrivateKey _issuerPrivateKey;

    private static PublicKey _publicKey;

    private static X509DistinguishedName _subjectDn;

    private static X509DistinguishedName _issuerDn;

    private static ValidityDates _validityDates;

    private static CryptoRandomInteger _cryptoRandomInteger;

    @BeforeClass
    public static void setUp() throws GeneralCryptoLibException {

        Security.addProvider(new BouncyCastleProvider());

        AsymmetricService asymmetricService = new AsymmetricService();

        KeyPair keyPairForSigning =
            asymmetricService.getKeyPairForSigning();

        _publicKey = keyPairForSigning.getPublic();
        _issuerPrivateKey = keyPairForSigning.getPrivate();

        PrimitivesService primitivesService = new PrimitivesService();

        _cryptoRandomInteger =
            (CryptoRandomInteger) primitivesService
                .getCryptoRandomInteger();

        CryptoRandomString randomAttributeGenerator =
            (CryptoRandomString) primitivesService
                .get64CharAlphabetCryptoRandomString();

        String commonName = randomAttributeGenerator.nextRandom(10);
        String country = randomAttributeGenerator.nextRandom(2);
        String organizationalUnit =
            randomAttributeGenerator.nextRandom(10);
        String organization = randomAttributeGenerator.nextRandom(10);
        String locality = randomAttributeGenerator.nextRandom(10);

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(commonName, country);
        builder.addOrganization(organization);
        builder.addOrganizationalUnit(organizationalUnit);
        builder.addLocality(locality);

        _subjectDn = builder.build();
        _issuerDn = builder.build();

        Date notBefore = new Date(System.currentTimeMillis());
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, 1);
        Date notAfter = calendar.getTime();

        _validityDates = new ValidityDates(notBefore, notAfter);

    }

    @Test
    public void whenCreateBouncyCastleX509CertificateBuilderGivenDefaultProviderThenBuild()
            throws GeneralCryptoLibException {

        X509Certificate cert = createAndBuildCertificate(_configDefault);

        assertNotNull(cert);
    }

    @Test
    public void whenCreateBouncyCastleX509CertificateBuilderGivenBCProviderThenBuild()
            throws GeneralCryptoLibException {

        X509Certificate cert = createAndBuildCertificate(_configBC);

        assertNotNull(cert);
    }

    private X509Certificate createAndBuildCertificate(
            final ConfigX509CertificateAlgorithmAndProvider config)
            throws GeneralCryptoLibException {

        X509Certificate cert =
            new BouncyCastleX509CertificateBuilder(config.getAlgorithm(),
                config.getProvider(), _publicKey, _subjectDn, _issuerDn,
                _validityDates, _cryptoRandomInteger)
                .build(_issuerPrivateKey);

        return cert;
    }

}
