/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.technicalconnector.tests.soap;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import javax.activation.DataHandler;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.w3c.dom.Document;


/**
 * Class to intercept and verifies SOAPMessage and return a fixed response
 * 
 * @author EH053
 * 
 */
public class SOAPConnectionFactory extends javax.xml.soap.SOAPConnectionFactory {

    private static Queue<SOAPMessage> responsesQueue = new LinkedList<SOAPMessage>();

    private static List<SOAPMessageAsserter> asserters = new ArrayList<SOAPMessageAsserter>();

    private static final MessageFactory MF;

    static {
        try {
            MF = MessageFactory.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public SOAPConnection createConnection() throws SOAPException {
        return new SOAPConnection() {

            @Override
            public void close() throws SOAPException {
                //
            }

            @Override
            public SOAPMessage call(SOAPMessage request, Object to) throws SOAPException {
                return invokeStub(request, to);
            }

            private SOAPMessage invokeStub(SOAPMessage request, Object to) throws SOAPException {
                for (SOAPMessageAsserter asserter : asserters) {
                    asserter.assertSOAPMessage(request);
                }
                SOAPMessage msg = responsesQueue.poll();
                if (msg == null) {
                    throw new SOAPException("Response Queue is empty.");
                }
                return msg;
            }
        };
    }

    public static List<SOAPMessageAsserter> getAsserters() {
        return asserters;
    }

    public static void clearQueue() {
        responsesQueue.clear();
    }

    /**
     * Method to add a SOAPMessage to the responses {@link Queue}
     */
    public static void addSOAPMessageToQueue(Document payload, Map<String, DataHandler> handlers, List<SOAPHeaderElement> headerItems) throws SOAPException {
        responsesQueue.add(generateSOAPMessage(payload, handlers, headerItems));
    }

    public static SOAPMessage generateSOAPMessage(Document payload, Map<String, DataHandler> handlers, List<SOAPHeaderElement> headerItems) throws SOAPException {
        SOAPMessage response = MF.createMessage();
        // Get SOAPPart
        SOAPPart soapPart = response.getSOAPPart();
        // get SOAPEnvelope
        SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
        if (headerItems != null) {
            for (SOAPHeaderElement headerElement : headerItems) {
                soapEnvelope.getHeader().addChildElement(headerElement);
            }
        }
        // get SOAPBody
        SOAPBody soapBody = soapEnvelope.getBody();
        // set the payload
        soapBody.addDocument(payload);
        // addAttachement
        if (handlers != null) {
            for (String key : handlers.keySet()) {
                AttachmentPart part = response.createAttachmentPart(handlers.get(key));
                part.setContentType(handlers.get(key).getContentType());
                part.setContentId(key);
                response.addAttachmentPart(part);
            }
        }
        return response;
    }
}
