/*
 * Copyright (c) eHealth
 */
using System;
using be.ehealth.technicalconnector.session;
using be.ehealth.technicalconnector.utils;
using NUnit.Framework;
using java.security;
using be.ehealth.business.common.domain;
using be.ehealth.business.mycarenetcommons.builders;
using be.ehealth.business.mycarenetcommons.domain;
using be.ehealth.business.mycarenetcommons.exception;
using be.ehealth.businessconnector.dmg.domain;
using be.ehealth.technicalconnector.enumeration;
using be.fgov.ehealth.technicalconnector.tests.utils;
using be.fgov.ehealth.technicalconnector.tests.session;
using be.fgov.ehealth.globalmedicalfile.core.v1;
using be.fgov.ehealth.globalmedicalfile.protocol.v1;
using be.ehealth.businessconnector.dmg.exception;

namespace be.ehealth.businessconnector.dmg.builders
{
	[TestFixture]
	public class CommonBuilderIntegrationTest
	{
		[SetUp]
		public static void init() {
			SessionInitializer.init(".\\be.ehealth.businessconnector.dmg.test.properties", SupportedLanguages.NET.getAbbreviation());
		}

		[TearDown]
		public static void tearDown() {
			Session.getInstance().unloadSession();
		}
		
		[Test]
		public void consultOK() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		public void consultOKNonDeflate() {
			generateBasicTestWithoutHash(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void consultERRORInputRefNull() {
			generateBasicTest(TestAction.consult, null, "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void consultERRORRefDateNull() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", null, ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");

		}
		
		[Test]
		[ExpectedException( typeof( InvalidBlobContentConnectorException ) )]
		public void consultERRORBlobContentNull(){
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), null, "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( InvalidBlobContentConnectorException ) )]
		public void consultERRORBlobContentTypeNull() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", null);
		}
		
		//TODO prc DmgBusinessConnectorException >< InvalidBlobContentConnectorException
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void consultERRORBlobIdNull() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), null, "String");

		}
		
		[Test]
		public void notifyOK() {
			generateBasicTest(TestAction.notify, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void notifyERRORInputRefNull(){
			generateBasicTest(TestAction.notify, null, "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void notifyERRORRefDateNull() {
			generateBasicTest(TestAction.notify, "1", "301", "4654454545678", "67032004773", null, ConnectorIOUtils.toBytes("message", Charset.UTF_8), "a1", "String");
		}
		
		[Test]
		[ExpectedException( typeof( InvalidBlobContentConnectorException ) )]
		public void notifyERRORBlobContentNull() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), null, "a1", "String");

		}
		
		[Test]
		[ExpectedException( typeof( InvalidBlobContentConnectorException ) )]
		public void notifyERRORBlobContentTypeNull(){
			generateBasicTest(TestAction.notify, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), null, "a1", "String");
		}
		
		//TODO prc DmgBusinessConnectorException >< InvalidBlobContentConnectorException
		[Test]
		[ExpectedException( typeof( DmgBusinessConnectorException ) )]
		public void notifyERRORBlobIdNull() {
			generateBasicTest(TestAction.consult, "1", "301", "4654454545678", "67032004773", new org.joda.time.DateTime(), ConnectorIOUtils.toBytes("message", Charset.UTF_8), null, "String");

		}
		
		
		public SendRequestType generateBasicTest(TestAction action, String inputRef, String mutuality, String regnrwithmut, String inss, org.joda.time.DateTime dateref, byte[] blobcontent, String blobid, String blobcontenttype) {
			
			String reference = inputRef;
			Patient pI = new Patient();
			pI.setMutuality(mutuality);
			pI.setRegNrWithMut(regnrwithmut);
			pI.setInss(inss);
			
			BlobBuilder bbuilder = RequestBuilderFactory.getBlobBuilder("dmg");
			Blob blob = bbuilder.build(blobcontent, "deflate", blobid, blobcontenttype);
			MessageDigest md = MessageDigest.getInstance("SHA-256");
			byte[] buffhash = blobcontent;
			md.update(buffhash);
			blob.setHashValue(md.digest());
			
			RequestObjectBuilder builder = RequestObjectBuilderFactory.getRequestObjectBuilder();
			SendRequestType result = null;
			switch (action) {
				case TestAction.consult:
					result = builder.buildSendConsultRequest(true, reference, pI, dateref, blob, null);
					Assert.IsNull(result.getXadesT());
					break;
				case TestAction.notify:
					result = builder.buildSendNotifyRequest(true, reference, pI, dateref, blob, null);
					Assert.IsNotNull(result.getXadesT());
					break;
			}
			
			// Check all values
			Assert.AreEqual(reference, result.getCommonInput().getInputReference(), "inputreference incorrect");
			Assert.IsNotNull(result.getCommonInput().getOrigin());
			
			RequestType rT = new RequestType();
			rT.setIsTest(true);
			Assert.AreEqual(rT.isIsTest(), result.getCommonInput().getRequest().isIsTest(), "istest incorrect");
			
			Assert.AreEqual(dateref.toDateMidnight(), result.getRouting().getReferenceDate().toDateMidnight(), "Dateref incorrect");
			// TODO prc null >< mutuality ?
			Assert.AreEqual(mutuality, result.getRouting().getCareReceiver().getMutuality(), "Mut incorrect");
			Assert.AreEqual(regnrwithmut, result.getRouting().getCareReceiver().getRegNrWithMut(), "RegNrWithMut incorrect");
			Assert.AreEqual(pI.getInss(), result.getRouting().getCareReceiver().getSsin(), "Ssin incorrect");
			Assert.IsNull(result.getRouting().getPeriod());
			
			Assert.AreEqual(blobid, result.getDetail().getId(), "Blob id type incorrect");
			Assert.AreEqual(blobcontenttype, result.getDetail().getContentType(), "Blob content type incorrect");
			Assert.AreEqual("deflate", result.getDetail().getContentEncoding(), "Blob content encodingincorrect");
			
			Blob resultBlob = new Blob();
			resultBlob.setContent(result.getDetail().getValue());
			resultBlob.setContentEncoding("deflate");
			resultBlob.setHashValue(blob.getHashValue());
			Assert.AreEqual(ConnectorIOUtils.toString(blobcontent, Charset.UTF_8), ConnectorIOUtils.toString(bbuilder.checkAndRetrieveContent(resultBlob), Charset.UTF_8), "Blob content incorrect");
			Assert.AreEqual(blob.getHashValue(), result.getDetail().getHashValue(), "Blob content hashValue incorrect");
			
			return result;
		}
		
		public SendRequestType generateBasicTestWithoutHash(TestAction action, String inputRef, String mutuality, String regnrwithmut, String inss, org.joda.time.DateTime dateref, byte[] blobcontent, String blobid, String blobcontenttype) {
			
			String reference = inputRef;
			
			Patient pI = new Patient();
			pI.setMutuality(mutuality);
			pI.setRegNrWithMut(regnrwithmut);
			pI.setInss(inss);
			
			BlobBuilder bbuilder = RequestBuilderFactory.getBlobBuilder("dmg");
			Blob blob = bbuilder.build(blobcontent, "none", blobid, blobcontenttype);
			
			RequestObjectBuilder builder = RequestObjectBuilderFactory.getRequestObjectBuilder();
			SendRequestType result = null;
			switch (action) {
				case TestAction.consult:
					result = builder.buildSendConsultRequest(true, reference, pI, dateref, blob, null);
					break;
				case TestAction.notify:
					result = builder.buildSendNotifyRequest(true, reference, pI, dateref, blob, null);
					break;
			}
			
			// Check all values
			Assert.AreEqual(reference, result.getCommonInput().getInputReference(), "inputreference incorrect");
			Assert.IsNotNull(result.getCommonInput().getOrigin());
			
			RequestType rT = new RequestType();
			rT.setIsTest(true);
			Assert.AreEqual(rT.isIsTest(), result.getCommonInput().getRequest().isIsTest(), "istest incorrect");
			
			Assert.AreEqual(dateref.toDateMidnight(), result.getRouting().getReferenceDate().toDateMidnight(), "Dateref incorrect");
			Assert.AreEqual(mutuality, result.getRouting().getCareReceiver().getMutuality(), "Mut incorrect");
			Assert.AreEqual(regnrwithmut, result.getRouting().getCareReceiver().getRegNrWithMut(), "RegNrWithMut incorrect");
			Assert.AreEqual(pI.getInss(), result.getRouting().getCareReceiver().getSsin(), "Ssin incorrect");
			Assert.IsNull(result.getRouting().getPeriod());
			
			Assert.AreEqual(blobid, result.getDetail().getId(), "Blob id type incorrect");
			Assert.AreEqual(blobcontenttype, result.getDetail().getContentType(), "Blob content type incorrect");
			Assert.AreEqual("none", result.getDetail().getContentEncoding(), "Blob content encodingincorrect");
			
			Blob resultBlob = new Blob();
			resultBlob.setContent(result.getDetail().getValue());
			resultBlob.setContentEncoding(result.getDetail().getContentEncoding());
			resultBlob.setHashTagRequired(action != TestAction.consult);// no hashtag needed for consult
			resultBlob.setHashValue(result.getDetail().getHashValue());
			Assert.AreEqual(ConnectorIOUtils.toString(blobcontent, Charset.UTF_8), ConnectorIOUtils.toString(bbuilder.checkAndRetrieveContent(resultBlob), Charset.UTF_8), "Blob content incorrect");
			
			Assert.IsNull(result.getXadesT());
			
			return result;
		}
	}
}
