#region Header

/*
 * Copyright (c) eHealth
 */

#endregion Header

/**
 * IntegrationTest for Registration Authority
 */
namespace be.fgov.ehealth.technicalconnector.ra
{


	using be.ehealth.technicalconnector.beid;
	using be.ehealth.technicalconnector.config;
	using be.ehealth.technicalconnector.service.sts.security.impl.beid.impl;
	using be.ehealth.technicalconnector.session;
	using be.ehealth.technicalconnector.utils;
	using be.fedict.commons.eid.client;

	using java.util;
	using java.lang;
	using java.io;
	using java.awt;
	using org.apache.commons.io;
	using org.joda.time;

	using NUnit.Framework;
	
	using be.ehealth.technicalconnector.service.sts.security;
	using be.ehealth.technicalconnector.service.sts.security.impl;
	using be.fgov.ehealth.technicalconnector.ra.builders;
	using be.fgov.ehealth.technicalconnector.ra.domain;
	using be.fgov.ehealth.technicalconnector.ra.enumaration;
	using be.fgov.ehealth.technicalconnector.ra.service;
	using be.fgov.ehealth.technicalconnector.ra.utils;

	using java.security;
	using java.security.cert;

	[TestFixture]
	public class RaWalkThroughIntegrationTest
	{

		private static string TEMP_DIR = System.getProperty("java.io.tmpdir");


		[Test]
		[ExpectedException( "RaException" )]
		public void walkEID() {
			KeyPair authenticationKeyPair = CertificateUtils.generateKeyPair();

			NewCertificateContract contract = (NewCertificateContract) BuilderFactory.newContractBuilder().create()//
				.withEid()//
				.withPrivatePhone("027875111").withPrivateEmail("hannes.declercq@ehealth.fgov.be")//
				.generatePKCS10(authenticationKeyPair)//
				.useLanguage(Language.NL)//
				.build();

			walk(contract, authenticationKeyPair);

		}

		[Test]
		public void walkOrganization() {
			KeyPair authenticationKeyPair = CertificateUtils.generateKeyPair();

			NewCertificateContract contract = (NewCertificateContract)BuilderFactory.newContractBuilder().create()//
				.forOrganization().withId("89999865", IdentifierType.NIHII_LABO).withName("LABORATORY WB").withApplicationId(UUID.randomUUID().toString().Trim("-".ToCharArray()).Substring(0, 29))//
				.withPrivatePhone("027875111").withPrivateEmail("hannes.declercq@ehealth.fgov.be")//
				.generatePKCS10(authenticationKeyPair)//
				.useLanguage(Language.NL)//
				.build();

			walk(contract, authenticationKeyPair);

		}

		public void walk(NewCertificateContract contract, KeyPair authenticationKeyPair) {
			char[] passwd = "15".ToCharArray();

			view(contract);

			string storeLocation = TEMP_DIR + contract.getDistinguishedName().asNormalisedBaseFileName();

			AuthenticationCertificateRegistrationService certRA = ServiceFactory.getAuthenticationCertificateRegistrationService();
			string requestId = certRA.request(contract);

			KeyStoreUtils store = new KeyStoreUtils();
			store.addAuthenticationKeyPair(authenticationKeyPair, passwd);
			store.store(storeLocation, passwd);

			Result result = poll(certRA, requestId);

			store.addAuthenticationChain(passwd, (X509Certificate)result.getResult());
			store.store(storeLocation, passwd);


			X509Certificate[] resultCert = (X509Certificate[])result.getResult();
			Credential cred = new KeyPairCredential(authenticationKeyPair.getPrivate(), resultCert[0]);
			EncryptionTokenRegistrationService etkRA = ServiceFactory.getEncryptionTokenRegistrationService(cred);

			KeyPair etkKeyPair = CertificateUtils.generateKeyPair();

			byte[] challenge = etkRA.registerPublicKey(etkKeyPair.getPublic());
			
			store.addEncryptionToken(etkKeyPair, passwd, CertificateUtils.generateCert(etkKeyPair));

			store.store(storeLocation, passwd);

			X509Certificate etkCert = BuilderFactory.newEncryptionTokenBuilder(cred).create()//
				.withKeyPair(etkKeyPair)//
				.withChallenge(challenge)//
				.build();

			etkRA.registerToken(etkCert.getEncoded());

			store.addEncryptionToken(etkKeyPair, passwd, etkCert);

			store.store(storeLocation, passwd);

		}


		private Result poll(AuthenticationCertificateRegistrationService certRA, string requestId) {
			Result result = certRA.poll(requestId);
			while (result.getStatus().equals(Status.PENDING)) {
				long duration = new Duration(new DateTime(), result.getTime()).getMillis();
				if (duration > 0) {
					Thread.sleep(duration);
				}
				result = certRA.poll(requestId);
			}
			if (result.hasStatusError()) {
				throw new IllegalArgumentException(result.getStatus().name());
			}
			return result;
		}

		private static void view(Contract contract) {
			File htmlFile = File.createTempFile("contract", ".html");
			htmlFile.deleteOnExit();
			IOUtils.copy(new StringReader(contract.getContract()), new FileWriter(htmlFile));
			Desktop.getDesktop().browse(htmlFile.toURI());
		}


	}
}