using be.ehealth.business.mycarenetdomaincommons.domain;
using be.ehealth.businessconnector.genericasync.domain;
using be.ehealth.businessconnector.mycarenet.memberdataasync.session;
using be.ehealth.technicalconnector.exception;
using be.ehealth.technicalconnector.utils;
using be.fgov.ehealth.technicalconnector.tests.utils;
using be.fgov.ehealth.technicalconnector.tests.session;
using org.apache.commons.io;
using javax.xml.ws.soap;
using java.io;
using java.util.concurrent;

using NUnit.Framework;
using System;

namespace be.ehealth.businessconnector.memberdataasync.session
{
	
	public abstract class AbstractAsyncIntegrationTest {
	
	    private static string REQUEST_FOLDER = ".\\examples\\memberdata\\async\\request\\";
	
	    private static string EXPECTED_FOLDER = ".\\examples\\memberdata\\async\\response\\";
	
	    private static string VALID_REQUEST = "anh-request-detail.xml";
	
	    private static string VALID_RESPONSE = "anh-response-detail.xml";
	
	    private static string INVALID_REQUEST = "ans-request-detail.xml";
	
	    private static int SLEEP_TIME = 70;
	
	    private string enehID;
	
	    private string enxsID;
	
	    private string cnchID;
	
	    private string cnxsID;
	
	    public AbstractAsyncIntegrationTest(string enehID, string enxsID, string cnchID, string cnxsID) {
	        this.enehID = enehID;
	        this.enxsID = enxsID;
	        this.cnchID = cnchID;
	        this.cnxsID = cnxsID;
	    }
	    
	    [SetUp]
		public abstract void init();
	    
	    [TearDown]
		public void tearDown() {
			SessionDestroyer.destroy();
		}
	
	    [Test]
	    public void postMDAEncryptedWithSoapFault() {
	        Assert.Throws<SOAPFaultException>(() =>
            {
 	            testInvalidPost(enxsID, true);
			});
	    }
	
	    [Test]
	    public void postMDAEncrypted() {
	        testValidPost(enehID, true);
	    }
	
	  	[Test]
	    public void postMDAWithSoapFault() {
	        Assert.Throws<SOAPFaultException>(() =>
            {
	            testInvalidPost(cnxsID, false);
			});
	    }
	
	    [Test]
	    public void postMDA() {
	        testValidPost(cnchID, false);
	    }
	
	    private void testValidPost(string id, bool isEncrypted) {
	    	confirmAllMessages(getResponse());
	        postRequest(id, VALID_REQUEST, isEncrypted);
	        ProcessedGetResponse response = getResponse();
	        confirmAllMessages(response);
	        verifyResponse(response);
	    }
	
	    private void testInvalidPost(string id, bool isEncrypted) {
	        postRequest(id, INVALID_REQUEST, isEncrypted);
	    }
	
	    private void verifyResponse(ProcessedGetResponse response) {
	        InputStream inStream = ConnectorIOUtils.getResourceAsStream(EXPECTED_FOLDER + VALID_RESPONSE);
	        String expectedresponse = ConnectorIOUtils.convertStreamToString(inStream);
	        IOUtils.closeQuietly(inStream);
	
	        Assert.IsFalse(response.getMsgResponses().isEmpty());
	        ProcessedMsgResponse msgResponse = (ProcessedMsgResponse)response.getMsgResponses().get(0);
	        byte[] businessResponse = (byte[]) msgResponse.getBusinessResponse();
	        String actualResponse = System.Text.Encoding.Default.GetString(businessResponse);
	        XmlAsserter.assertSimilar(expectedresponse,actualResponse);
	    }
	
	    private void postRequest(string id, string requestXml, bool isEncrypted) {
	        byte[] bytes = ConnectorIOUtils.getResourceAsByteArray(REQUEST_FOLDER + requestXml);
	        InputReference inputReference = new InputReference(id);
	        if (isEncrypted) {
	            MemberDataSessionServiceFactory.getMemberDataService().postEncryptedMDAXml(bytes, inputReference);
	        } else {
	            MemberDataSessionServiceFactory.getMemberDataService().postMDAXml(bytes, inputReference);
	        }
	        waitSomeTimeBeforeProceeding();
	    }
	
	    private ProcessedGetResponse getResponse() {
	        ProcessedGetResponse response = MemberDataSessionServiceFactory.getMemberDataService().getMDAXml(GetRequest.newBuilder().withDefaults().build());
	        waitSomeTimeBeforeProceeding();
	        return response;
	    }
	
	    private void confirmAllMessages(ProcessedGetResponse response) {
	    	java.util.List msgResponses = response.getMsgResponses();
	    	for (int i=0; i<msgResponses.size(); ++i) {
	    		ProcessedMsgResponse msgResponse = (ProcessedMsgResponse) msgResponses.get(i);
	    		MemberDataSessionServiceFactory.getMemberDataService().confirmMessage(msgResponse);
	    		waitSomeTimeBeforeProceeding();
	    	}
	    }
	
	    private void waitSomeTimeBeforeProceeding() {
	        TimeUnit.SECONDS.sleep(SLEEP_TIME);
	    }
	
	}

}
