/*
 * Copyright (c) eHealth
 */
using System;
using be.ehealth.business.mycarenetcommons.builders;
using be.ehealth.business.mycarenetcommons.util;
using be.ehealth.businessconnector.genericasync.builders;
using be.ehealth.businessconnector.genericasync.mappers;
using be.ehealth.technicalconnector.config.util;
using be.ehealth.technicalconnector.config.util.domain;
using be.ehealth.technicalconnector.handler.domain;
using be.ehealth.technicalconnector.idgenerator;
using be.ehealth.technicalconnector.session;
using be.ehealth.technicalconnector.utils;
using be.fgov.ehealth.technicalconnector.tests.session;
using be.fgov.ehealth.technicalconnector.tests.utils;
using java.io;
using java.lang;
using java.net;
using NUnit.Framework;
using be.cin.mycarenet.esb.common.v2;
using be.cin.nip.async.generic;
using be.ehealth.businessconnector.genericasync.session;

namespace be.ehealth.businessconnector.invoicing
{
	[TestFixture]
	public class GetAndConfirmIntegrationTest
	{
		private static string PROJECT_NAME = "invoicing";

    	private static bool CONFIRM_MESSAGES = false;
    
		[SetUp]
	    public static void init() {
	    	SessionInitializer.init(".\\be.ehealth.businessconnector.invoicing.test.properties",SupportedLanguages.NET.getAbbreviation());
		}
	
	    [TearDown]
	    public static void tearDown() {
	        Session.getInstance().unloadSession();
	    }
    
		[Test]
	    public void postGetAndConfirmTest() {
	        PackageInfo packageInfo = ConfigUtil.retrievePackageInfo("genericasync." + PROJECT_NAME);
	        CommonBuilder commonBuilder = RequestBuilderFactory.getCommonBuilder(PROJECT_NAME);
	        OrigineType origin = CommonInputMapper.mapOrigin(commonBuilder.createOrigin(packageInfo));
	
	        GenAsyncService service = GenAsyncSessionServiceFactory.getGenAsyncService(PROJECT_NAME);
	        java.lang.Thread.sleep(750);
	        GetResponse responseGet = getMessages(origin, service);
			if (CONFIRM_MESSAGES) {
	            java.util.List msgHashValues = getMessageHashValues(responseGet);
	            java.util.List tackHashValues = getTackHashValues(responseGet);
	            
	            ConfirmResponse confirmResponse = confirmTheseMessages(origin, service, msgHashValues, tackHashValues);
	            
	            java.lang.Thread.sleep(750);
	            Assert.NotNull(confirmResponse);
	            // now you shouldn't receive those messages anymore
	            bool stillMessagesPresent = checkIfMessagesAreStillReturned(origin, service, msgHashValues, tackHashValues);
	            if (stillMessagesPresent) {
	                // someTimes they are processed a bit slower, so we retry a few times
	                java.lang.Thread.sleep(750);
	                stillMessagesPresent = checkIfMessagesAreStillReturned(origin, service, msgHashValues, tackHashValues);
	                if (stillMessagesPresent) {
	                    java.lang.Thread.sleep(3000);
	                    stillMessagesPresent = checkIfMessagesAreStillReturned(origin, service, msgHashValues, tackHashValues);
	                }
	            }
	            Assert.IsFalse(stillMessagesPresent, "there were still messages received which were acknowledged");
	        }
	
	    }
	    
	    /**
	     * @param origin
	     * @param service
	     * @return
	     * @throws URISyntaxException
	     * @throws TechnicalConnectorException
	     * @throws GenAsyncBusinessConnectorException
	     * @throws SessionManagementException
	     * @throws InstantiationException
	     */
	    private GetResponse getMessages(OrigineType origin, GenAsyncService service) {
	        MsgQuery msgQuery = new MsgQuery();
	        msgQuery.setInclude(new java.lang.Boolean(true));
	        msgQuery.setMax(new java.lang.Integer(100));
	        msgQuery.getMessageNames().add("HCPFAC");
	        msgQuery.getMessageNames().add("HCPAFD");
	        msgQuery.getMessageNames().add("HCPVWR");
	        
	        Query tackQuery = new Query();
	        tackQuery.setInclude(new java.lang.Boolean(true));
	        tackQuery.setMax(new java.lang.Integer(100));
	
	        WsAddressingHeader responseGetHeader = new WsAddressingHeader(new URI("urn:be:cin:nip:async:generic:get:query"));
	        responseGetHeader.setMessageID(new URI(IdGeneratorFactory.getIdGenerator("uuid").generateId()));
	        GetResponse responseGet = service.getRequest(BuilderFactory.getRequestObjectBuilder(PROJECT_NAME).buildGetRequest(origin, msgQuery, tackQuery), responseGetHeader);
	        writeToFile(ConnectorXmlUtils.toByteArray(responseGet), "getResponse");
	        ConnectorXmlUtils.logXmlObject(responseGet);
	        return responseGet;
	    }
	    
	     /**
	     * @param content
	     * @param location
	     * @throws TechnicalConnectorException
	     * @throws IOException
	     */
	    public void writeToFile(byte[] content, string fileName) {
	        string userHome = java.lang.System.getProperty("user.home");
	        if (userHome == null) {
	            throw new IllegalStateException("user.home==null");
	        }
	        File home = new File(userHome);
	        File sendFilesDir = new File(home, "invoicingSendFiles");
	        sendFilesDir.mkdir();
	        java.io.File contentFile = File.createTempFile(fileName, ".xml", sendFilesDir);
	        contentFile.createNewFile();
	        
	        FileWriter writer = new FileWriter(contentFile);
	        writer.write(System.Text.Encoding.UTF8.GetString(content));
	        writer.flush();
	        writer.close();
	    }
	
	    /**
	     * @param responseGet
	     * @return
	     */
	    private java.util.List getTackHashValues(GetResponse responseGet) {
	        java.util.List tackHashValues = new java.util.ArrayList();
	        java.util.List tackValues = responseGet.getReturn().getTAckResponses();
	        for (int i = 0; i < tackValues.size(); i++){
	        	TAckResponse tackResponse = (TAckResponse) tackValues.get(i);
	            byte[] hashValue = tackResponse.getTAck().getValue();
	            tackHashValues.add(hashValue);
	        }
	        return tackHashValues;
	    }
	
	    /**
	     * @param responseGet
	     * @return
	     */
	    private java.util.List getMessageHashValues(GetResponse responseGet) {
	        java.util.List msgHashValues = new java.util.ArrayList();
	        java.util.List msgValues = responseGet.getReturn().getMsgResponses();
	        for (int i = 0; i < msgValues.size(); i++){
	        	MsgResponse msgResp = (MsgResponse) msgValues.get(i);
	            byte[] hashValue = msgResp.getDetail().getHashValue();
	            msgHashValues.add(hashValue);
	        }
	        return msgHashValues;
	    }
	
	    /**
	     * @param origin
	     * @param service
	     * @param msgHashValues
	     * @param tackHashValues
	     * @return
	     * @throws URISyntaxException
	     * @throws TechnicalConnectorException
	     * @throws GenAsyncBusinessConnectorException
	     * @throws SessionManagementException
	     */
	    private ConfirmResponse confirmTheseMessages(OrigineType origin, GenAsyncService service, java.util.List msgHashValues, java.util.List tackHashValues) {
	        WsAddressingHeader responseConfirmHeader = WsAddressingUtil.createHeader(null,"urn:be:cin:nip:async:generic:confirm:hash");
	        
	        Confirm request = new Confirm();
	        request.setOrigin(origin);
	        request.getMsgHashValues().addAll(msgHashValues);
	        request.getTAckContents().addAll(tackHashValues);
	        ConfirmResponse confirmResponse = service.confirmRequest(request, responseConfirmHeader);
	        return confirmResponse;
	    }
	    
	    /**
	     * @param origin
	     * @param service
	     * @param msgHashValues
	     * @param tackHashValues
	     * @param stillMessagesPresent
	     * @return
	     * @throws URISyntaxException
	     * @throws TechnicalConnectorException
	     * @throws GenAsyncBusinessConnectorException
	     * @throws SessionManagementException
	     * @throws InstantiationException
	     */
	    private bool checkIfMessagesAreStillReturned(OrigineType origin, GenAsyncService service, java.util.List msgHashValues, java.util.List tackHashValues) {
	        bool stillMessagesPresent = false;
	        GetResponse messages = getMessages(origin, service);
	        Responses messageReturn = messages.getReturn();
	        if (messageReturn.getMsgCount() != 0 || messageReturn.getTAckCount() != 0) {
		        java.util.List msgValues = messageReturn.getMsgResponses();
		        for (int i = 0; i < msgValues.size(); i++){
		        	MsgResponse msgResponse = (MsgResponse) msgValues.get(i);
	                byte[] hashValue = msgResponse.getDetail().getHashValue();
	                if (msgHashValues.contains(hashValue)) {
	                    string msg = "   messageResponse found even after its reception was already confirmed : hashValue: >" + hashValue + "< , inputRef : " + msgResponse.getCommonOutput().getInputReference() + " outputRef: " + msgResponse.getCommonOutput().getOutputReference();
	                    Assert.Fail(msg);
	                }
		        }
		        java.util.List tackValues = messageReturn.getTAckResponses();
		        for (int i = 0; i < tackValues.size(); i++){
		        	TAckResponse tackResp = (TAckResponse) tackValues.get(i);
	                byte[] value = tackResp.getTAck().getValue();
	                if (tackHashValues.contains(value)) {
	                    string msg = "   TackResponse found after it was already confirmed : hashValue: >" + value + "< , appliesTo >" + tackResp.getTAck().getAppliesTo() + "< " + tackResp.getTAck().getResultMessage();
	                    stillMessagesPresent = true;
	                }               
	            }
	        }
	        return stillMessagesPresent;
	    }
	}
}
