using be.fgov.ehealth.technicalconnector.ra.exceptions;
#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]
		public void listApplicationIds() {
			Organization organization = new Organization("0809394427", IdentifierType.CBE, "EHP");
			java.util.List applicationIdList = BuilderFactory.newInformationBuilder().listActiveApplicationIds().forOrganization(organization);
			Assert.AreNotEqual(0, applicationIdList.size());
		}

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

			NewCertificateContract contract = (NewCertificateContract) BuilderFactory.newContractBuilder().create()
				.withEid()
				.withPrivatePhone("028918647")
				.withPrivateEmail("guillaume.strauven@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 = pollFunction(certRA, requestId);

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


			Credential cred = new KeyPairCredential(authenticationKeyPair.getPrivate(), ((X509Certificate[])result.getResult())[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 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());
		}
		
		private Result pollFunction(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;
		}
	}
}