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

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Map;

import mockit.Mock;
import mockit.MockUp;

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.certificates.factory.CryptoX509Certificate;
import com.scytl.cryptolib.primitives.primes.utils.PemUtils;
import com.scytl.cryptolib.scytl.keystore.cryptoapi.CryptoAPIScytlKeyStore;
import com.scytl.products.ov.config.utils.KeyPairValidator;
import com.scytl.products.ov.utils.KeyStoreLoader;
import com.scytl.products.ov.utils.PasswordReaderUtils;

public class GenerateCommandTest {

	public static final String OUTPUT_PATH = "target/generatePlatformRoot/";

	public static final char[] PASSWORD = "1111111111111111".toCharArray();

	public static final String PRIVATE_KEY_ALIAS = "privatekey";

	public static final String PLATFORM_NAME = "foo";

	private static Map<String, String> params2values;

	private GenerateCommand _sut;

	@BeforeClass
	public static void setUp() {

		Security.addProvider(new BouncyCastleProvider());

		String[] inputParams = {"-out", OUTPUT_PATH, "-name", PLATFORM_NAME };
		params2values = Action.GEN_ROOT.validateAndArrange(inputParams);

	}

	@Test
	public void generateThePlatformRootKeys() throws GeneralCryptoLibException, IOException {

		_sut = new GenerateCommand();

		new MockUp<PasswordReaderUtils>() {

			@Mock
			public char[] readPasswordFromConsoleAndConfirm() {
				return "1111111111111111".toCharArray();
			}
		};

		_sut.execute(params2values);

		Path pathCertificate = Paths.get(OUTPUT_PATH, PLATFORM_NAME + "RootCA.pem");
		assertThat(Files.exists(pathCertificate), is(true));

		Path pathKeyStore = Paths.get(OUTPUT_PATH, PLATFORM_NAME + "RootCA.sks");
		assertThat(Files.exists(pathKeyStore), is(true));

		CryptoAPIScytlKeyStore rootKeyStore = KeyStoreLoader.loadPlatformRootKeyStore(pathKeyStore, PASSWORD);
		PrivateKey privatekey = rootKeyStore.getPrivateKeyEntry(PRIVATE_KEY_ALIAS, PASSWORD);
		PublicKey keyStoreCertPubKey = rootKeyStore.getCertificateChain(PRIVATE_KEY_ALIAS)[0].getPublicKey();
		X509Certificate certificate =
			(X509Certificate) PemUtils.certificateFromPem(new String(Files.readAllBytes(pathCertificate),
				StandardCharsets.UTF_8));

		CryptoX509Certificate cryptoCert = new CryptoX509Certificate(certificate);
		cryptoCert.getSubjectDn().getCommonName().contains(PLATFORM_NAME);
		Date notBefore = cryptoCert.getNotBefore();
		Date notAfter = cryptoCert.getNotAfter();
		assertThat(notAfter.after(notBefore), is(true));

		KeyPairValidator validator = new KeyPairValidator();
		validator.validateKeyPair(keyStoreCertPubKey, privatekey);

		PublicKey certPubKey = certificate.getPublicKey();
		validator.validateKeyPair(certPubKey, privatekey);

	}

}
