/*
 * Copyright (c) eHealth
 */
using System;
using System.IO;
using ikvm.extensions;
using NUnit.Framework;
using java.security;
using java.util;
using be.ehealth.businessconnector.chapterIV.builders;
using be.ehealth.businessconnector.chapterIV.domain;
using be.ehealth.businessconnector.chapterIV.testutil;
using be.ehealth.technicalconnector.service.sts.security;
using be.ehealth.technicalconnector.service.sts.security.impl;
using be.fgov.ehealth.technicalconnector.tests.session;
using be.fgov.ehealth.technicalconnector.tests.utils;
using be.ehealth.technicalconnector.utils;
using be.ehealth.technicalconnector.utils.impl;
using be.ehealth.technicalconnector.service.etee.impl;
using be.fgov.ehealth.etee.crypto.utils;
using be.ehealth.technicalconnector.service.etee;
using be.ehealth.businessconnector.chapterIV.validators.impl;
using be.fgov.ehealth.chap4.protocol.v1;
using be.ehealth.technicalconnector.exception;
using be.ehealth.technicalconnector.session;
using XmlUnit;

/**
 * tests the {@link ResponseBuilderImpl} class.
 * 
 * @author EHP
 * 
 */
namespace be.ehealth.businessconnector.chapterIV.builders.impl
{
	[TestFixture]
	public class ResponseBuilderIntegrationTest
	{
		private static java.util.Properties props = null;
		private ResponseBuilder responseBuilder;
		
		[SetUp]
		public void setup() {
			props = TestPropertiesLoader.getProperties(".\\be.ehealth.businessconnector.chapterIV.test.properties",SupportedLanguages.NET.getAbbreviation());
			SessionInitializer.init(props, SupportedLanguages.NET.getAbbreviation());
	        KeyStore keystore = KeyStore.getInstance("PKCS12");
	        char[] password = props.getProperty("test.expired.keystore.password").ToCharArray();
	        keystore.load(ConnectorIOUtils.getResourceAsStream(props.getProperty("test.expired.keystore.location")), password);
	        Enumeration enums = keystore.aliases();
	        while (enums.hasMoreElements()) {
	            String alias = (String) enums.nextElement();
	            if (keystore.isKeyEntry(alias) && !alias.Equals("authentication")) {
	                Session.getInstance().getSession().getEncryptionPrivateKeys().put(alias, (PrivateKey) keystore.getKey(alias, password));
	                Session.getInstance().getSession().getHolderOfKeyPrivateKeys().put(alias, (PrivateKey) keystore.getKey(alias, password));
	            }
	        }
			responseBuilder = BuilderFactory.getBuilderFactoryForSession().getResponseBuilder();
		}
		
		[TearDown]
		public void tearDown() {
			Session.getInstance().unloadSession();
		}
		
		
		[Test]
	    public void testRetrieveKmehrResponseIgnoreWarningsTrue() {
	        ConsultChap4MedicalAdvisorAgreementResponse agreementResponse = TestUtils.mapToConsultResponseObject(".\\examples\\response\\successfullResponse.xml");
	        bool expectedError = !isDoctor() || !isHannes();
	
	        try {
	            responseBuilder.validateTimestampAndretrieveChapterIVKmehrResponseWithTimeStampInfo(agreementResponse, true);
	            Assert.False(expectedError, "An UnsealConnectorException should have been thrown");
	        } catch (UnsealConnectorException e) {
	            // we expect an UnsealConnectoException if the user is not Hannes or not a doctor
	            if (!expectedError) {
	                throw e;
	            }
	        }
	    }
		
		
		/**
	     * If Hannes is not the doctor, the UnsealConnectorException is thrown because the certificate is not valid for the content of the message (because it's encrypted for another person)
	     * Otherwise, the exception is thrown because the certificate is expired.
	     * @throws Exception
	     */
	    [Test]
	    [ExpectedException( typeof( UnsealConnectorException ) )]
	    public void testRetrieveKmehrResponseExpiredCertificateIgnoreWarningsFalse() {
	        ConsultChap4MedicalAdvisorAgreementResponse agreementResponse = TestUtils.mapToConsultResponseObject(".\\examples\\response\\successfullResponse_expiredcert.xml");
	        responseBuilder.validateTimestampAndretrieveChapterIVKmehrResponseWithTimeStampInfo(agreementResponse, false);
	    }
	    
	    [Test]
		public void testRetrieveKmehrResponseExpiredCertificateIgnoreWarningsTrue() {
        	bool expectedError = !isDoctor() || !isHannes();
        	try {
	            ConsultChap4MedicalAdvisorAgreementResponse agreementResponse = TestUtils.mapToConsultResponseObject(".\\examples\\response\\successfullResponse_expiredcert.xml");

	            ChapterIVKmehrResponseWithTimeStampInfo validateTimestampAndretrieveChapterIVKmehrResponseWithTimeStampInfo = responseBuilder.validateTimestampAndretrieveChapterIVKmehrResponseWithTimeStampInfo(agreementResponse, true);

	            string actual = System.Text.Encoding.UTF8.GetString(validateTimestampAndretrieveChapterIVKmehrResponseWithTimeStampInfo.getKmehrResponseBytes());

	            string expectedFileLocation = TestUtils.getFileContents(".\\examples\\response\\contentKmehrMessageInSuccessfulResponse_expiredcert.xml");

	            AssertExpectedResult(actual, expectedFileLocation,true);

	        } catch (UnsealConnectorException e) {
	            // we expect an UnsealConnectoException if the user is not Hannes or not a doctor
	            if (!expectedError) {
	                throw e;
	            }
	        }
	    }
	    
    	private void AssertExpectedResult(string input1, string input2, bool expected) {
            TextReader reader1 = new StringReader(ConnectorXmlUtils.flatten(input1));
            TextReader reader2 = new StringReader(ConnectorXmlUtils.flatten(input2));
            XmlDiff xmld = new XmlDiff(reader1,reader2);
            
            DiffResult result = xmld.Compare();
            string msg = string.Format("comparing {0} to {1}: {2}", input1, input2, result.Difference);
            Assert.AreEqual(expected, result.Equal, msg);
        }
    
		private bool isDoctor() {
			return "persphysician".Equals(props.getProperty("session.professionType"));
		}
		
		private bool isHannes() {
			return "hannes".Equals(props.getProperty("session.username"));
		}
	}
}
