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

import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.EnumSet;
import java.util.Set;

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

import com.scytl.products.ov.commons.infrastructure.remote.client.NodeIdentifier;

/**
 * @author jbarrio
 * @date 23/11/16
 *
 * Copyright (C) 2016 Scytl Secure Electronic Voting SA
 *
 * All rights reserved.
 */
public class KeystoreTest {

	@BeforeClass
	public static void runOnceSetup() {
		Security.addProvider( new BouncyCastleProvider() );
	}

	@Test
	public void test()
	{
		try {
			final KeystoreReader keystoreReader = TestKeystoreReader.getInstance();
			
			final Certificate rootCertificate = keystoreReader.readRootCertificate();
			Assert.assertNotNull( rootCertificate );
			
			System.out.println("\n-Root certificate:\n" + SecurityUtils.certificateToString( rootCertificate ));
			
			final Set<NodeIdentifier> signingNodes = EnumSet.allOf( NodeIdentifier.class );
/*			signingNodes.add( NodeIdentifier.ADMIN_PORTAL );
			signingNodes.add( NodeIdentifier.API_GATEWAY );
			signingNodes.add( NodeIdentifier.AUTHENTICATION );
			signingNodes.add( NodeIdentifier.CONFIG_PLATFORM_ROOT );
			signingNodes.add( NodeIdentifier.SECURE_DATA_MANAGER );
*/
			
			// removing MD from the list since this does not need signing keys (for now)
			signingNodes.remove(NodeIdentifier.MIXDEC); 
			
			for (final NodeIdentifier nodeIdentifier : signingNodes)
			{
				System.out.println("\nSigning node: " + nodeIdentifier.getName() + " (" + nodeIdentifier.getAlias() + ")\n");
				
				// Passwords
				
				final KeystorePasswordsReader keystorePasswordsReader = TestKeystorePasswordsReader.getInstance( nodeIdentifier );
				final KeystorePasswords keystorePasswords = keystorePasswordsReader.read( );
				Assert.assertNotNull( keystorePasswords );
				
				final AbstractKeystorePasswords readableKeystorePasswords = (AbstractKeystorePasswords) keystorePasswords;
				
				Assert.assertNotNull( readableKeystorePasswords.getPrivateKeystorePassword() );
				System.out.println("-Private keystore password--->" + readableKeystorePasswords.getPrivateKeystorePassword() + "<---\n");
				
				Assert.assertNotNull( readableKeystorePasswords.getSigningPrivateKeyPassword() );
				System.out.println("-Signing private key password--->" + readableKeystorePasswords.getSigningPrivateKeyPassword() + "<---\n");

//				Assert.assertNotNull( readableKeystorePasswords.getEncryptionPrivateKeyPassword() );
//				System.out.println("-Encryption private key password--->" + readableKeystorePasswords.getEncryptionPrivateKeyPassword() + "<---\n");
				
				// Private keys
				
				final PrivateKey signingPrivateKey = keystoreReader.readSigningPrivateKey( nodeIdentifier, keystorePasswords );
				Assert.assertNotNull(signingPrivateKey);
				System.out.println("-Signing private key:\n" + SecurityUtils.privateKeyToString( signingPrivateKey ));
				
				final PrivateKey encryptionPrivateKey = keystoreReader.readEncryptionPrivateKey( nodeIdentifier, keystorePasswords );
				Assert.assertNull( encryptionPrivateKey );
				System.out.println("-Encryption private key: <null>\n");
				
				// Destroy passwords
				
				System.out.println( "-Before passwords destroy:\n" + readableKeystorePasswords.getString() + "\n");
				keystorePasswords.destroy();
				Assert.assertTrue( keystorePasswords.isDestroyed() );
				System.out.println( "-After passwords destroy:\n" + readableKeystorePasswords.getString() + "\n" );
				
				keystorePasswordsReader.destroy();
				Assert.assertTrue( keystorePasswordsReader.isDestroyed() );
				
				// Certificates
				
				final Certificate signingCertificate = keystoreReader.readSigningCertificate( nodeIdentifier) ;
				Assert.assertNotNull( signingCertificate );
				System.out.println("-Signing certificate:\n" + SecurityUtils.certificateToString( signingCertificate ));
				
				final Certificate encryptionCertificate = keystoreReader.readEncryptionCertificate( nodeIdentifier ) ;
				Assert.assertNull( encryptionCertificate );
				System.out.println("-Encryption certificate: <null>\n");
			}
			
			// Currently this part of the test is ignored (no non-singing modules are available that
			// need logging keys), since we do not have any module that encrypts and signs logs based on the
			// generated certificates, so the resulting set will be empty.
			final Set<NodeIdentifier> nonSigningNodes = EnumSet.allOf( NodeIdentifier.class );
			nonSigningNodes.removeAll( signingNodes );
			for (final NodeIdentifier nodeIdentifier : nonSigningNodes)
			{
				System.out.println("\nNon-signing node: " + nodeIdentifier.getName() + " (" + nodeIdentifier.getAlias() + ")\n");
				
				// Private keys
				
				final PrivateKey signingPrivateKey = keystoreReader.readSigningPrivateKey( nodeIdentifier, "" );
				Assert.assertNull(signingPrivateKey);
				System.out.println("-Signing private key: <null>\n");
				
				final PrivateKey encryptionPrivateKey = keystoreReader.readEncryptionPrivateKey( nodeIdentifier, "" );
				Assert.assertNull(encryptionPrivateKey);
				System.out.println("-Encryption private key: <null>\n");
				
				// Certificates
				
				final Certificate signingCertificate = keystoreReader.readSigningCertificate( nodeIdentifier );
				Assert.assertNull( signingCertificate );
				System.out.println("-Signing certificate: <null>\n");
				
				final Certificate encryptionCertificate = keystoreReader.readEncryptionCertificate( nodeIdentifier );
				Assert.assertNull( encryptionCertificate );
				System.out.println("-Encryption certificate: <null>\n");
			}
			System.out.println("\n\n");
		}
		catch (final Exception exception) {
			throw new RuntimeException( exception );
		}
	}
	
}
