/*
 * Copyright (c) eHealth
 */
using System;
using be.ehealth.business.mycarenetdomaincommons.mapper;
using be.ehealth.business.mycarenetdomaincommons.util;
using ikvm.extensions;
using java.lang;
using NUnit.Framework;
using java.io;
using java.net;
using java.util;
using org.joda.time;
using be.cin.mycarenet.esb.common.v2;
using be.cin.nip.async.generic;
using be.ehealth.business.mycarenetdomaincommons.builders;
using be.ehealth.business.mycarenetdomaincommons.domain;
using be.ehealth.businessconnector.genericasync.builders;
using be.ehealth.businessconnector.genericasync.mappers;
using be.ehealth.businessconnector.genericasync.service;
using be.ehealth.businessconnector.genericasync.test.util;
using be.ehealth.technicalconnector.config.util;
using be.ehealth.technicalconnector.exception;
using be.ehealth.technicalconnector.handler.domain;
using be.ehealth.technicalconnector.idgenerator;
using be.ehealth.technicalconnector.utils;
using be.ehealth.businessconnector.genericasync.session;
using be.ehealth.technicalconnector.config.util.domain;
using be.ehealth.business.mycarenetdomaincommons.util;
using org.mapstruct.factory;

namespace be.ehealth.businessconnector.genericasync.integration
{
	/**
	 * tests the retrieval of a consultation list.
	 * 
	 * @author EHP
	 * 
	 */
	public class GenAsyncIntegrationTestUtil
	{
		/**
	     * 
	     */
	    private GenAsyncIntegrationTestUtil() {
	    }
	    
	    public static void basePostTest(PostParameter postParameter) {

	
	        /*
	         * MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hash = expected; md.update(hash); blob.setHashValue(md.digest());
	         */
	
	        post(postParameter);
	
	        PackageInfo packageInfo = McnConfigUtil.retrievePackageInfo(postParameter.serviceName);
        	CommonBuilder commonBuilder = RequestBuilderFactory.getCommonBuilder(postParameter.serviceName);
        	CommonInputMapper mapper = (CommonInputMapper) Mappers.getMapper(typeof(CommonInputMapper));
        	OrigineType origin = mapper.map(commonBuilder.createOrigin(packageInfo));
	
	        System.Threading.Thread.Sleep(5000);
	        GetResponse getResponse = get(origin, postParameter.serviceName, null);
	
	        Assert.True(getResponse.getReturn().getMsgCount() > 0 || getResponse.getReturn().getTAckCount() > 0, "there should at least be a return for msg or tack, now both lists are empty");
	        confirm(getResponse, origin, postParameter.serviceName);
	    }
	
	    /**
	     * @param getResponse
	     * @param origin
	     */
	    public static void confirm(GetResponse getResponse, OrigineType origin, string serviceName) {
	        confirm(origin, serviceName,new java.lang.Integer(0), getResponse.getReturn().getTAckResponses(), getResponse.getReturn().getMsgResponses());
	    }
	
	    /**
	     * @param getResponse
	     * @param origin
	     */
	    public static void confirm(OrigineType origin, string serviceName, Integer oaNumber, java.util.List tackResponses, java.util.List messageResponses) {

	        StringBuilder sb = new StringBuilder();
	        for (int i = 0;i<messageResponses.size();i++) {
	        	MsgResponse msgResponse = (MsgResponse)messageResponses.get(i);
	            string msg = "confirming message with inputReference " + msgResponse.getCommonOutput().getInputReference();
	            sb.append("\n").append(msg);
	            writeToFile(("confirming message with inputReference " + msgResponse.getCommonOutput().getInputReference()).getBytes(), "confirmedBusinessMessage" + msgResponse.getCommonOutput().getInputReference());
	        }
	        for (int i = 0;i<tackResponses.size();i++) {
	        	TAckResponse tAckResponse = (TAckResponse)tackResponses.get(i);
	            sb.append("\n tack : with Xades : ").append(tAckResponse.getXadesT() == null ? "no Xades" : "xades");
	            TestUtil.addTackToSb(sb, tAckResponse.getTAck());
	        }
	        writeToFile(sb.toString().getBytes(), "confirmedMessages" + new org.joda.time.DateTime().toString("yyyyMMddhhmmss"));
	        be.ehealth.businessconnector.genericasync.session.GenAsyncService service = (be.ehealth.businessconnector.genericasync.session.GenAsyncService)GenAsyncSessionServiceFactory.getGenAsyncService(serviceName);
	        Confirm confirmRequst = BuilderFactory.getRequestObjectBuilder(serviceName).buildConfirmRequest(origin, messageResponses, tackResponses);
	        writeToFile(ConnectorXmlUtils.toByteArray(confirmRequst), "confirmRequest");
	        string oa = "";
            if (oaNumber != null) {
                oa = oaNumber.toString();
            }
	        ConfirmResponse responseConfirm = service.confirmRequest(confirmRequst, WsAddressingUtil.createHeader(oa, "urn:be:cin:nip:async:generic:confirm:hash"));
	        ConnectorXmlUtils.dump(responseConfirm);
	
	    }
	
	    /**
	     * @param tAckResponses
	     * @param tackSucces
	     * @return
	     */
	    public static java.util.List selectTacksWithStatus(java.util.List tAckResponses, string status) {
	        java.util.ArrayList result = new java.util.ArrayList();
	        for (int i = 0; i < tAckResponses.size(); i++) {
	        	TAckResponse tAckResponse = (TAckResponse)tAckResponses.get(i);
	            if (status.Equals(tAckResponse.getTAck().getResultMajor())) {
	                result.add(tAckResponse);
	            }
	        }
	        return result;
	    }
	
	    /**
	     * retrieves asynchronous messages that may be waiting.
	     * 
	     * @param origin {@link OrigineType} the originator of the this get request
	     * @param serviceName the servicename , used to retrieve config properties from config file
	     * @param messageNames the types of messages , if no messageNames are given all messages are returned ex : "GMD-CONSULT-HCP",
	     *        "GMD-CLOSURE", "GMD-EXTENSION"
	     * @return {@link GetResponse}
	     * @throws Exception
	     */

	    public static GetResponse get(OrigineType origin, string serviceName, java.util.List messageNames = null) {
	        MsgQuery msgQuery = new MsgQuery();
	    	msgQuery.setInclude(java.lang.Boolean.TRUE);
	        msgQuery.setMax(new java.lang.Integer(100));
	        // if no messages are added , all messages are returned
	        msgQuery.getMessageNames().clear();
	        if (messageNames != null) {
	        	for (int i=0;i<messageNames.size();i++) {
	        		string messageName = (string)messageNames.get(i);
	                msgQuery.getMessageNames().add(messageName);
	            }
	        }
	
	        Query tackQuery = new Query();
	        tackQuery.setInclude(java.lang.Boolean.TRUE);
	        tackQuery.setMax(new java.lang.Integer(100));
	
	        WsAddressingHeader responseGetHeader = WsAddressingUtil.createHeader(null,"urn:be:cin:nip:async:generic:get:query");
	        responseGetHeader.setMessageID(new URI(IdGeneratorFactory.getIdGenerator("uuid").generateId()));
	        be.ehealth.businessconnector.genericasync.session.GenAsyncService service = (be.ehealth.businessconnector.genericasync.session.GenAsyncService)GenAsyncSessionServiceFactory.getGenAsyncService(serviceName);
	        GetResponse responseGet = service.getRequest(BuilderFactory.getRequestObjectBuilder(serviceName).buildGetRequest(origin, msgQuery, tackQuery), responseGetHeader);
	        writeToFile(ConnectorXmlUtils.toByteArray(responseGet), "getResponse");
	        ConnectorXmlUtils.dump(responseGet);
	        return responseGet;
	    }
	
	    /**
	     * parameters used to call generic async.
	     * 
	     * @author EHP
	     * 
	     */
	    public class PostParameter {
	
	        /**
	         * String which identifies the request, to be used in InputReference and as second part of the kmehr id.
	         */
	        public string requestIdentifier;
	
	        /**
	         * the Blob object to send with the business content.
	         */
	        public Blob blob;
	
	        /**
	         * boolean indicating its a test.
	         */
	        public bool istest;
	
	        /**
	         * the service name , used to retrieve parameters from config file.
	         */
	        public string serviceName;
	
	        /**
	         * boolean indicating if we must use xades or not. currently Xades is not supported and value true will cause an
	         * UnsupportedOperationException.
	         */
	        public bool useXades;
	
	        /**
	         * optional : the oaNumber to set in the to part of the header.
	         */
	        public java.lang.Integer oaNumber;
	
	        /**
	         * the url to use for the
	         */
	        public string addressingHeaderUrl;
	
	        /**
	         * 
	         */
	        public PostParameter(Blob blob, bool istest, string serviceName, bool useXades, java.lang.Integer oaNumber, string addressingHeaderUrl, string requestIdentifier) {
	            this.blob = blob;
	            this.istest = istest;
	            this.serviceName = serviceName;
	            this.useXades = useXades;
	            this.oaNumber = oaNumber;
	            this.addressingHeaderUrl = addressingHeaderUrl;
	            this.requestIdentifier = requestIdentifier;
	        }
	
	        /**
	         * @param blob the blob to set
	         */
	        public void setBlob(Blob blob) {
	            this.blob = blob;
	        }
	
	        /**
	         * @param istest the istest to set
	         */
	        public void setIstest(bool istest) {
	            this.istest = istest;
	        }
	
	        /**
	         * @param serviceName the serviceName to set
	         */
	        public void setServiceName(string serviceName) {
	            this.serviceName = serviceName;
	        }
	
	        /**
	         * @param useXades the useXades to set
	         */
	        public void setUseXades(bool useXades) {
	            this.useXades = useXades;
	        }
	
	        /**
	         * @param oaNumber the oaNumber to set
	         */
	        public void setOaNumber(java.lang.Integer oaNumber) {
	            this.oaNumber = oaNumber;
	        }
	
	        /**
	         * @param addressingHeaderUrl the addressingHeaderUrl to set
	         */
	        public void setAddressingHeaderUrl(string addressingHeaderUrl) {
	            this.addressingHeaderUrl = addressingHeaderUrl;
	        }
	    }
	
	    /**
	     * @param content
	     * @param location
	     * @throws TechnicalConnectorException
	     * @throws IOException
	     */
	    public static void writeToFile(byte[] content, string fileName) {
	        string userHome = java.lang.System.getProperty("user.home");
	        if (userHome == null) {
	            throw new java.lang.IllegalStateException("user.home==null");
	        }
	        java.io.File home = new java.io.File(userHome);
	        java.io.File sendFilesDir = new java.io.File(home, "genAsyncSendFiles");
	        sendFilesDir.mkdir();
	        java.io.File contentFile = java.io.File.createTempFile(fileName, ".xml", sendFilesDir);
	        contentFile.createNewFile();
	        FileWriter writer = new FileWriter(contentFile);
	        writer.write(System.Text.Encoding.UTF8.GetString(content));
	        writer.flush();
	        writer.close();
	    }
	
	
	    /**
	     * 
	     */
	    public static PostResponse post(PostParameter parameterObject) {
	        if (parameterObject.useXades) {
	            throw new java.lang.UnsupportedOperationException("test utility does not support xades yet ");
	        }
	    	CommonInputMapper mapper = (CommonInputMapper) Mappers.getMapper(typeof(CommonInputMapper));
	        be.cin.mycarenet.esb.common.v2.CommonInput ci = mapper.map(RequestBuilderFactory.getCommonBuilder("genericasync").createCommonInput(McnConfigUtil.retrievePackageInfo("genericasync." + parameterObject.serviceName), parameterObject.istest, parameterObject.requestIdentifier));
	        be.cin.types.v1.Blob det = DomainBlobMapper.mapBlobToCinBlob(parameterObject.blob);
	        // no xades needed for dmg async
	        Post post = BuilderFactory.getRequestObjectBuilder(parameterObject.serviceName).buildPostRequest(ci, det, null);
	
	        be.ehealth.businessconnector.genericasync.session.GenAsyncService service = GenAsyncSessionServiceFactory.getGenAsyncService(parameterObject.serviceName);
	        WsAddressingHeader header = new WsAddressingHeader(new URI(parameterObject.addressingHeaderUrl));
	        header.setTo(new URI(""));
	        header.setFaultTo("http://www.w3.org/2005/08/addressing/anonymous");
	        header.setReplyTo("http://www.w3.org/2005/08/addressing/anonymous");
	        if (parameterObject.oaNumber != null) {
	            header.setTo(new URI("urn:nip:destination:io:" + parameterObject.oaNumber));
	        }
	        header.setMessageID(new URI(IdGeneratorFactory.getIdGenerator("uuid").generateId()));
	
	        PostResponse responsePost = service.postRequest(post, header);
	        storePostAndResponseInFiles(post, responsePost, parameterObject.serviceName, parameterObject.blob);
	        ConnectorXmlUtils.dump(responsePost);
	
	        ResponseObjectBuilder responseBuilder = BuilderFactory.getResponseObjectBuilder();
	        bool hasWarnings = responseBuilder.handlePostResponse(responsePost);
	        return responsePost;
	    }
	
	    /**
	     * @param post
	     * @param responsePost
	     */
	    private static void storePostAndResponseInFiles(Post post, PostResponse responsePost, string serviceName, Blob blob)  {
	
	        writeToFile(ConnectorXmlUtils.toByteArray(post), serviceName + post.getCommonInput().getInputReference() + "PostObject");
	        writeToFile(ConnectorXmlUtils.toByteArray(responsePost), serviceName + post.getCommonInput().getInputReference() + "responsePost");
	        string fileName = serviceName + post.getCommonInput().getInputReference() + "blobContent";
	        byte[] content = blob.getContent();
	        if ("none".Equals(blob.getContentEncoding())) {
	            writeToFile(content, fileName);
	        } else {
	            byte[] decompress = ConnectorIOUtils.decompress(content);
	            writeToFile(decompress, fileName);
	        }
	
	    }
	}
}
