/*
 * Copyright (c) eHealth
 */
using System;
using ikvm.extensions;
using java.lang;
using NUnit.Framework;
using java.io;
using java.net;
using java.util;
using org.xml.sax;
using be.ehealth.businessconnector.ehbox.api.domain;
using be.ehealth.businessconnector.ehbox.api.utils;
using be.ehealth.businessconnector.ehbox.v3.builders;
using be.ehealth.businessconnector.ehbox.v3.session;
using be.ehealth.technicalconnector.exception;
using be.ehealth.technicalconnector.utils;
using be.fgov.ehealth.commons.core.v1;
using be.fgov.ehealth.ehbox.consultation.protocol.v3;
using be.fgov.ehealth.ehbox.core.v3;
using be.ehealth.technicalconnector.exception;
using be.fgov.ehealth.technicalconnector.tests.utils;

namespace be.ehealth.businessconnector.ehboxv3.service
{
    [TestFixture]
    public class EhboxTestUtilities
    {
        /**
         * only static methods needed.
         */
        private EhboxTestUtilities() {
        }
        
        
        /**
         * safest way to delete without exceptions. determines boxIdToUse message by message.
         * 
         * @throws ConnectorException
         */
        public static void safeDeleteAllMessageOneByOne() {
            EhealthBoxServiceV3 service = be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory.getEhealthBoxServiceV3();
            
            for (int i = 0; i < EhboxTestUtilities.getListOfAllSources().size(); i++) {
                string source = (string)EhboxTestUtilities.getListOfAllSources().get(i);
                GetMessageListResponseType allEhboxesMessagesList = service.getAllEhboxesMessagesList(BuilderFactory.getRequestBuilder().createAllEhboxesMessagesListRequest(source));
                for (int j = 0; i < allEhboxesMessagesList.getMessages().size(); i++) {
                    be.fgov.ehealth.ehbox.consultation.protocol.v3.Message message = (be.fgov.ehealth.ehbox.consultation.protocol.v3.Message)allEhboxesMessagesList.getMessages().get(j);
                    BoxIdType boxIdToUse = mapSender(message.getSender());
                    service.deleteMessage(BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, boxIdToUse, message.getMessageId()));
                }
            }
            
        }
        /**
         * @param sender
         * @return
         */
        private static BoxIdType mapSender(SenderType sender) {
            if (sender != null) {
                BoxIdType boxIdType = new BoxIdType();
                boxIdType.setId(sender.getId());
                boxIdType.setQuality(sender.getQuality());
                boxIdType.setType(sender.getType());
                boxIdType.setSubType(sender.getSubType());
                return boxIdType;
            }
            return null;
        }
        
        public static void deleteAllMessagesForSource(string source, BoxIdType boxId) {
            EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
            GetMessageListResponseType messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
            deleteMessages(source, messagesList, boxId);
            messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
            while (messagesList.getMessages().size() > 0) {
                deleteMessages(source, messagesList, boxId);
                messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
            }
            
        }
        
        /**
         * @param source
         * @param allEhboxesMessagesList
         * @param boxId the ehealthbox to use
         * @throws ConnectorException
         */
        private static void deleteMessages(string source, GetMessageListResponseType allEhboxesMessagesList, BoxIdType boxId) {
            Set messageIdsToDelete = new HashSet();
            for (int i = 0; i < allEhboxesMessagesList.getMessages().size(); i++) {
                be.fgov.ehealth.ehbox.consultation.protocol.v3.Message messageToDelete = (be.fgov.ehealth.ehbox.consultation.protocol.v3.Message)allEhboxesMessagesList.getMessages().get(i);
                messageIdsToDelete.add(messageToDelete.getMessageId());
                logMessage(messageToDelete);
            }
            deleteMessages(source, messageIdsToDelete, boxId);
        }
        
        /**
         * @param source
         * @param messageIdsToDelete
         * @param boxId the ehealthbox to use
         * @return
         * @throws ConnectorException
         */
        private static void deleteMessages(string source, Set messageIdsToDelete, BoxIdType boxId) {
            if (messageIdsToDelete.isEmpty()) {
                return;
            }
            string[] messageIdsToDeleteArray = (string[]) messageIdsToDelete.toArray(new string[]{});
            DeleteMessageResponse deleteMessages = deleteMessagesArray(source, messageIdsToDeleteArray);
            Assert.True("100".Equals(deleteMessages.getStatus().getCode()));
        }
        
        public static DeleteMessageResponse deleteMessagesArray(string source, string[] messageIds) {
            DeleteMessageRequest request = BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, messageIds);
            EhealthBoxServiceV3 service = be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory.getEhealthBoxServiceV3();
            DeleteMessageResponse response = service.deleteMessage(request);
            Assert.True("100".Equals(response.getStatus().getCode()));
            return response;
        }
        
        /**
         * @param message
         */
        public static void logMessage(be.fgov.ehealth.ehbox.consultation.protocol.v3.Message message) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            logMessage(message, sb);
            System.Console.WriteLine(sb.toString());
        }
        
        /**
         * compares a jaxb object with the expected xml.
         * 
         * @param fileLocation the file location of the expected xml file.
         * @param jaxbObject jaxbObject
         * @throws IOException
         * @throws SAXException
         * @throws TechnicalConnectorException
         */
        public static void compareXmlWithExpectedFile(string fileLocation, object jaxbObject) {
            InputStream xmlFile = ConnectorIOUtils.getResourceAsStream(fileLocation);
            string expected = System.Text.Encoding.UTF8.GetString(ConnectorIOUtils.getBytes(xmlFile));
            string actualXml = ConnectorXmlUtils.toString(jaxbObject);
            System.Console.WriteLine("compareXmlWithExpectedFile : actual\n" + actualXml + "\n \nexpected\n" + expected);
            XmlAsserter.assertSimilar(expected, actualXml);
            
        }
        
        /**
         * @param buildFullMessage
         */
        public static void logFullMessage(be.ehealth.businessconnector.ehbox.api.domain.Message message) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder("logging message :\n");
            sb.append("\n  message.getPublicationDateTime():").append(message.getPublicationDateTime()).append("\n");
            sb.append("\n  message.getPublicationId():").append(message.getPublicationId()).append("\n");
            sb.append("\n  message.getSender():").append(message.getSender()).append("\n");
            GetFullMessageResponse original = (GetFullMessageResponse)message.getOriginal();
            sb.append("\n  original.getId():").append(original.getId()).append("\n");
            sb.append("\n  original.getStatus().getCode():").append(original.getStatus().getCode()).append("\n");
            for (int i = 0; i < original.getStatus().getMessages().size(); i++) {
                LocalisedString localisedString = (LocalisedString)original.getStatus().getMessages().get(i);
                sb.append("\n  original.getStatus().getMessages().localisedString.getValue();:").append(localisedString.getValue()).append("\n");
            }
            
            sb.append("\n  original.getMessageInfo().getPublicationDate():").append(original.getMessageInfo().getPublicationDate()).append("\n");
            System.Console.WriteLine("logFullMessage : " + sb.toString());
        }
        
        public static void logStackTrace(java.lang.Throwable e) {
            java.lang.StackTraceElement[] stackTrace = e.getStackTrace();
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            sb.append(e.getMessage()).append("\n");
            for (int i = 0; i<stackTrace.Length; i++) {
                java.lang.StackTraceElement stackTraceElement = (java.lang.StackTraceElement)stackTrace[i];
                sb.append(stackTraceElement.getClassName()).append(".").append(stackTraceElement.getMethodName());
                sb.append(":").append(stackTraceElement.getLineNumber()).append("\n");
            }
            System.Console.WriteLine("logStackTrace : \n" + sb.toString());
        }
        
        /**
         * @param source
         * @throws MalformedURLException
         * @throws TechnicalConnectorException
         * @throws EhboxBusinessConnectorException
         * @throws BusinessError
         * @throws SystemError
         */
        public static void showMessagesFromSource(string source) {
            GetMessageListResponseType response = EhboxTestUtilities.retrieveMessageFromSourceAndCheckStatus(source);
            // print out the messageId's for the given folder
            java.util.List list = response.getMessages();
            java.lang.StringBuilder errorDetailMessagesStringBuilder = new java.lang.StringBuilder();
            bool errorsFound = false;
            errorDetailMessagesStringBuilder.append("showMessagesFromSource " + source + ": number of messages: " + list.size());
            for (int i = 0 ; i < list.size(); i++) {
                be.fgov.ehealth.ehbox.consultation.protocol.v3.Message message = (be.fgov.ehealth.ehbox.consultation.protocol.v3.Message)list.get(i);
                try {
                    
                    be.ehealth.businessconnector.ehbox.api.domain.Message msg = BuilderFactory.getConsultationMessageBuilder().buildMessage(message);
                    if (msg.GetType() == typeof(ErrorMessage)) {
                        errorsFound = true;
                        ErrorMessage errorMessage = (ErrorMessage) msg;
                        GetFullMessageResponse fullMessage = EhboxTestUtilities.getFullMessage(source, errorMessage.getId());
                        be.ehealth.businessconnector.ehbox.api.domain.Message buildFullMessage = BuilderFactory.getConsultationMessageBuilder().buildFullMessage(fullMessage);
                        EhboxTestUtilities.appendErrorDescription(buildFullMessage, errorDetailMessagesStringBuilder);
                    }
                    
                } catch (java.lang.Exception e) {
                    System.Console.WriteLine("    exception " + e.getMessage() + " for message with id " + message.getMessageId());
                    System.Console.WriteLine("showMessagesFromSource : error occured , log till now : " + errorDetailMessagesStringBuilder.toString());
                    Assert.Fail("exception occured : " + e.getMessage());
                }
                logMessage(message, errorDetailMessagesStringBuilder);
                
            }
            if (errorsFound) {
                System.Console.WriteLine("testShowAllErrorMessagesForInbox : ERRORS FOUND :");
            } else {
                System.Console.WriteLine("testShowAllErrorMessagesForInbox : No error messages");
            }
            System.Console.WriteLine(errorDetailMessagesStringBuilder.toString());
        }
        
        /**
         * @param message
         * @param errorDetailMessagesStringBuilder
         */
        private static void logMessage(be.fgov.ehealth.ehbox.consultation.protocol.v3.Message message, java.lang.StringBuilder sb) {
            string title = message.getContentInfo() == null ? "NO CONTENTINFO TO RETRIEVE TITLE" : message.getContentInfo().getTitle();
            sb.append(" message  title :").append(title).append(" , messageType ").append(message.getClass().getCanonicalName()).append(" , id: ").append(message.getMessageId()).append(" publication date : ").append(message.getMessageInfo().getPublicationDate());
        }
        
        
        /**
         * @param buildFullMessage
         * @param sb
         */
        public static void appendErrorDescription(be.ehealth.businessconnector.ehbox.api.domain.Message buildFullMessage, java.lang.StringBuilder sb) {
            if (buildFullMessage.GetType() == typeof(ErrorMessage)) {
                ErrorMessage errorMessage = (ErrorMessage) buildFullMessage;
                sb.append("error : code =").append(errorMessage.getErrorCode()).append("  ");
                for (int i = 0; i<errorMessage.getErrorMsg().size(); i++) {
                    string errorMessageString = (string)errorMessage.getErrorMsg().get(i);
                    sb.append("[").append(errorMessageString).append("] ");
                }
                sb.append("\n");
            } else {
                Assert.Fail("logError called on non error object : error in test setup");
            }
            
        }
        
        /**
         * @param source
         * @return
         * @throws MalformedURLException
         * @throws TechnicalConnectorException
         * @throws EhboxBusinessConnectorException
         * @throws BusinessError
         * @throws SystemError
         */
        public static GetMessageListResponseType retrieveMessageFromSourceAndCheckStatus(string source) {
            GetMessagesListRequest request = new GetMessagesListRequest();
            request.setSource(source);
            
            
            /*
             * Invoke the business connector framework's eHealthBox's getMessageList operation
             */EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
            GetMessageListResponseType response = service.getMessageList(request);
            
            /*
             * Verify the response
             */
            // check if there are no errors
            Assert.AreEqual("100", response.getStatus().getCode());
            // check if a messageId has been returned
            Assert.IsNotNull(response.getMessages());
            return response;
        }
        
        /**
         * @param source
         * @param fullMessageId
         * @return
         * @throws MalformedURLException
         * @throws TechnicalConnectorException
         * @throws EhboxBusinessConnectorException
         * @throws BusinessError
         * @throws SystemError
         */
        public static GetFullMessageResponse getFullMessage(string source, string fullMessageId) {
            EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
            GetFullMessageRequest request = new GetFullMessageRequest();
            // set the messageId, use the messageId of the message that has been sent in testSendMessage
            // request.setMessageId(shortMessage.getMessageId());
            request.setMessageId(fullMessageId);
            request.setSource(source);
            
            /*
             * Invoke the business connector framework's eHealthBox's getFullMessage operation
             */
            
            GetFullMessageResponse response = service.getFullMessage(request);
            return response;
        }
        
        
        /**
         * @param boxId the ehealthbox to use
         * @param string
         * @throws ConnectorException
         */
        public static void deleteAllOutOfOfficesForCurrentUser(BoxIdType boxId) {
            EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
            GetOoOListResponse ooOList = service.getOoOList(BuilderFactory.getRequestBuilder().createGetOoOListRequest(boxId));
            java.util.List oOoIdList = new java.util.ArrayList();
            for (int i = 0 ; i < ooOList.getOoOs().size() ; i++) {
                OoO oOo = (OoO)ooOList.getOoOs().get(i);
                oOoIdList.add(oOo.getOoOId());
                System.Console.WriteLine("deleteAllOutOfOfficesForCurrentUser : adding delete id for oOo" + oOoToString(oOo));
            }
            if (!oOoIdList.isEmpty()) {
                DeleteOoOResponse deleteOoOResponse = service.deleteOoO(BuilderFactory.getRequestBuilder().createDeleteOoORequest(boxId, oOoIdList));
                Assert.AreEqual("100", deleteOoOResponse.getStatus().getCode(), "delete oo should have succeeded");
            } else {
                System.Console.WriteLine("deleteAllOutOfOfficesForCurrentUser : no Out off offices found");
            }
        }
        
        
        /**
         * @param oOo
         * @return
         */
        private static string oOoToString(OoO oOo) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            sb.append("[ id:)").append(oOo.getOoOId());
            sb.append("StartDate").append(oOo.getStartDate());
            sb.append("EndDate").append(oOo.getEndDate());
            for (int i = 0; i<oOo.getSubstitutes().size(); i++) {
                BoxIdType boxId = (BoxIdType)oOo.getSubstitutes().get(i);
                sb.append(" boxId:(").append(boxIdToString(boxId)).append(")");
            }
            return sb.toString();
        }
        
        
        /**
         * @param boxId
         * @return
         */
        private static object boxIdToString(BoxIdType boxId) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            sb.append(" [").append("id:").append(boxId.getId());
            sb.append(", quality:").append(boxId.getQuality());
            sb.append(", type:").append(boxId.getType());
            sb.append(", subType:").append(boxId.getSubType());
            sb.append("]");
            return sb.toString();
        }
        
        
        /**
         * @param sendDocument
         * @return
         * @throws UnsealConnectorException
         */
        public static string documentToString(Document doc) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            sb.append("Document[");
            sb.append(",fileName:").append(doc.getFilename());
            sb.append(",title:").append(doc.getTitle());
            sb.append(",mimeType:").append(doc.getMimeType());
            sb.append(", signing:").append(signingToString(doc.getSigning()));
            if (doc.getContent() != null && doc.getContent().Length > 0) {
                sb.append("content : \n").append(System.Text.Encoding.UTF8.GetString(doc.getContent())).append("\n");
            } else {
                sb.append("\n no content\n");
            }
            sb.append("]");
            
            return sb.toString();
        }
        
        
        /**
         * @param signing
         * @return
         */
        private static object signingToString(SigningValue signing) {
            java.lang.StringBuilder sb = new java.lang.StringBuilder();
            sb.append("SigningValue[");
            if (signing != null) {
                sb.append("downLoadFileName:").append(signing.getSigningDownloadFileName());
                sb.append(" ,signingType:").append(signing.getSigningType());
            }
            sb.append("]");
            return sb.toString();
        }
        
        
        /**
         * @param boxId
         * @return
         */
        public static Addressee mapBoxIdTypeToAddressee(BoxIdType boxId) {
            if (boxId == null) {
                return null;
            }
            // we only use a small subset of qualities
            QualityType type = null;
            if ("DOCTOR".Equals(boxId.getQuality())) {
                if ("NIHII".Equals(boxId.getType())) {
                    type = QualityType.GENERAL_PRACTIONER_NIHII;
                } else if ("INSS".Equals(boxId.getType())) {
                    type = QualityType.GENERAL_PRACTIONER_SSIN;
                }
            }
            if ("NURSE".Equals(boxId.getQuality())) {
                if ("NIHII".Equals(boxId.getType())) {
                    type = QualityType.NURSE_NIHII;
                } else if ("INSS".Equals(boxId.getType())) {
                    type = QualityType.NURSE_SSIN;
                }
            }
            if ("PHARMACY".Equals(boxId.getQuality())) {
                if ("NIHII".Equals(boxId.getType())) {
                    type = QualityType.PHARMACY_NIHII;
                } else {
                    throw new IllegalArgumentException("combination in boxId of " + boxId.getQuality() + " and " + boxId.getType() + " not supported : for PHARMACY only NIHII is allowed");
                }
            }
            if (type == null) {
                throw new UnsupportedOperationException("test mapping for this combination not provided : complete the method mapBoxIdTypeToAddressee in class " + typeof(EhboxTestUtilities).Name);
            }
            return new Addressee(boxId.getId(), type);
        }
        
        
        /**
         * @return
         */
        public static java.util.List getListOfAllSources() {
            java.util.List sources = new java.util.ArrayList();
            sources.add("INBOX");
            sources.add("SENTBOX");
            sources.add("BININBOX");
            sources.add("BINSENTBOX");
            return sources;
        }
        
        
        /**
         * @param destination
         * @return
         */
        public static BoxIdType mapDestinationToBoxIdType(EhboxIdentifierType destination) {
            BoxIdType boxIdType = new BoxIdType();
            boxIdType.setId(destination.getId());
            boxIdType.setQuality(destination.getQuality());
            boxIdType.setSubType(destination.getSubType());
            boxIdType.setType(destination.getType());
            return boxIdType;
        }
        
        /**
         * checks properties to see if these are tests for persphysician.
         * 
         * @param testConfigProperties
         * @return
         */
        public static bool isDoctorTest(Properties testConfigProperties) {
            return "persphysician".Equals(testConfigProperties.getProperty("session.professionType"));
        }
        
        /**
         * checks properties to see if these are tests for persphysician.
         * 
         * @param testConfigPropertiesFile
         * @return
         * @throws TechnicalConnectorException
         */
        public static bool isDoctorTest(string testConfigPropertiesFile) {
            return isDoctorTest( TestPropertiesLoader.getProperties(testConfigPropertiesFile));
        }
        
        

        public static void waitForProcessing() {
            try {
                System.Threading.Thread.Sleep(5000);
            } catch (java.lang.InterruptedException e) {
                //just go on
            }
        }
    }
}
