/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axis2.jaxws.message.impl;

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axis2.Constants.Configuration;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.message.Block;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.Protocol;
import org.apache.axis2.jaxws.message.XMLFault;
import org.apache.axis2.jaxws.message.XMLPart;
import org.apache.axis2.jaxws.message.attachments.AttachmentUtils;
import org.apache.axis2.jaxws.message.factory.BlockFactory;
import org.apache.axis2.jaxws.message.factory.SAAJConverterFactory;
import org.apache.axis2.jaxws.message.factory.SOAPEnvelopeBlockFactory;
import org.apache.axis2.jaxws.message.factory.XMLPartFactory;
import org.apache.axis2.jaxws.message.factory.XMLStringBlockFactory;
import org.apache.axis2.jaxws.message.util.MessageUtils;
import org.apache.axis2.jaxws.message.util.SAAJConverter;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.activation.DataHandler;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.ws.WebServiceException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * MessageImpl
 * A Message is an XML part + Attachments.
 * Most of the implementation delegates to the XMLPart implementation.
 * 
 * NOTE: For XML/HTTP (REST), a SOAP 1.1. Envelope is built and the rest payload is placed
 * in the body.  This purposely mimics the Axis2 implementation.
 */
public class MessageImpl implements Message {
    private static final Log log = LogFactory.getLog(MessageImpl.class);
    
    Protocol protocol = Protocol.unknown; // the protocol, defaults to unknown
    XMLPart xmlPart = null; // the representation of the xmlpart
    
    boolean mtomEnabled;
    
    // The transport headers are stored in a Map, which is the 
    // same data representation used by the Axis2 MessageContext (TRANSPORT_HEADERS).
    private Map transportHeaders = null; 
    
    // The Message is connected to a MessageContext.
    // Prior to that connection, attachments are stored locally
    // After the connection, attachments are obtained from the MessageContext
    Attachments attachments = new Attachments();  // Local Attachments
    private MessageContext messageContext;
    
    // Set after we have past the pivot point when the message is consumed
    private boolean postPivot = false;
    private boolean doingSWA = false;
    
    /**
     * MessageImpl should be constructed via the MessageFactory.
     * This constructor constructs an empty message with the specified protocol
     * @param protocol
     */
    MessageImpl(Protocol protocol) throws WebServiceException, XMLStreamException {
        createXMLPart(protocol);
    }
    
    /**
     * Message is constructed by the MessageFactory.
     * This constructor creates a message from the specified root.
     * @param root
     * @param protocol or null
     */
    MessageImpl(OMElement root, Protocol protocol) 
    throws WebServiceException, XMLStreamException  {
        createXMLPart(root, protocol);
    }
    
    /**
     * Message is constructed by the MessageFactory.
     * This constructor creates a message from the specified root.
     * @param root
     * @param protocol or null
     */
    MessageImpl(SOAPEnvelope root) throws WebServiceException, XMLStreamException  {
        createXMLPart(root);
    }
    
    /**
     * Create a new XMLPart and Protocol from the root
     * @param root SOAPEnvelope
     * @throws WebServiceException
     * @throws XMLStreamException
     */
    private void createXMLPart(SOAPEnvelope root) throws WebServiceException, XMLStreamException {
        XMLPartFactory factory = (XMLPartFactory) FactoryRegistry.getFactory(XMLPartFactory.class);
        xmlPart = factory.createFrom(root);
        this.protocol = xmlPart.getProtocol();
        xmlPart.setParent(this); 
    }
    
    /**
     * Create a new XMLPart and Protocol from the root
     * @param root OMElement
     * @throws WebServiceException
     * @throws XMLStreamException
     */
    private void createXMLPart(OMElement root, Protocol protocol) 
    throws WebServiceException, XMLStreamException {
        XMLPartFactory factory = (XMLPartFactory) FactoryRegistry.getFactory(XMLPartFactory.class);
        xmlPart = factory.createFrom(root, protocol);
        this.protocol = xmlPart.getProtocol();
        xmlPart.setParent(this);
    }
    
    /**
     * Create a new empty XMLPart from the Protocol
     * @param protocol
     * @throws WebServiceException
     * @throws XMLStreamException
     */
    private void createXMLPart(Protocol protocol) throws WebServiceException, XMLStreamException {
        this.protocol = protocol;
        if (protocol.equals(Protocol.unknown)) {
            throw ExceptionFactory.
            makeWebServiceException(Messages.getMessage("ProtocolIsNotKnown"));
        } 
        XMLPartFactory factory = (XMLPartFactory) FactoryRegistry.getFactory(XMLPartFactory.class);
        xmlPart = factory.create(protocol);
        xmlPart.setParent(this);
    }
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Message#getAsSOAPMessage()
     */
    public SOAPMessage getAsSOAPMessage() throws WebServiceException {
        
        // TODO: 
        // This is a non performant way to create SOAPMessage. I will serialize
        // the xmlpart content and then create an InputStream of byte.
        // Finally create SOAPMessage using this InputStream.
        // The real solution may involve using non-spec, implementation
        // constructors to create a Message from an Envelope
        try {
            if (log.isDebugEnabled()) {
                log.debug("start getAsSOAPMessage");
            }
            // Get OMElement from XMLPart.
            OMElement element = xmlPart.getAsOMElement();
            
            SOAPMessage soapMessage = getSAAJConverter().toSAAJ((org.apache.axiom.soap.SOAPEnvelope)element, false);
            
            // Get the namespace so that we can determine SOAP11 or SOAP12
            OMNamespace ns = element.getNamespace();
            
            // Get the MimeHeaders from the transportHeaders map
            MimeHeaders defaultHeaders = soapMessage.getMimeHeaders();
            if (transportHeaders != null) {
                Iterator it = transportHeaders.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry entry = (Map.Entry) it.next();
                    String key = (String) entry.getKey();
                    if (entry.getValue() == null) {
                        // This is not necessarily a problem; log it and make sure not to NPE
                        if (log.isDebugEnabled()) {
                            log.debug("  Not added to transport header. header =" + key + 
                                      " because value is null;");
                        }
                    }
                    else if (entry.getValue() instanceof String) {
                        // Normally there is one value per key
                        if (log.isDebugEnabled()) {
                            log.debug("  add transport header. header =" + key + 
                                      " value = " + entry.getValue());
                        }
                        defaultHeaders.addHeader(key, (String) entry.getValue());
                    } else {
                        // There may be multiple values for each key.  This code
                        // assumes the value is an array of String.
                        String values[] = (String[]) entry.getValue();
                        for (int i=0; i<values.length; i++) {
                            if (log.isDebugEnabled()) {
                                log.debug("  add transport header. header =" + key + 
                                          " value = " + values[i]);
                            }
                            defaultHeaders.addHeader(key, values[i]);
                        }
                    }
                }
            }
            
            // Toggle based on SOAP 1.1 or SOAP 1.2
            String contentType = null;
            if (ns.getNamespaceURI().equals(SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE)) {
                contentType = SOAPConstants.SOAP_1_1_CONTENT_TYPE;
            } else {
                contentType = SOAPConstants.SOAP_1_2_CONTENT_TYPE;
            }
            
            // Override the content-type
            String ctValue = contentType +"; charset=UTF-8";
            defaultHeaders.setHeader("Content-type", ctValue);
            if (log.isDebugEnabled()) {
                log.debug("  setContentType =" + ctValue);
            }
            
            // At this point the XMLPart is still an OMElement.  
            // We need to change it to the new SOAPEnvelope.
            createXMLPart(soapMessage.getSOAPPart().getEnvelope());
            
            // If axiom read the message from the input stream, 
            // then one of the attachments is a SOAPPart.  Ignore this attachment
            String soapPartContentID = getSOAPPartContentID();  // This may be null
            
            if (log.isDebugEnabled()) {
                log.debug("  soapPartContentID =" + soapPartContentID);
            }
            
            List<String> dontCopy = new ArrayList<String>();
            if (soapPartContentID != null) {
                dontCopy.add(soapPartContentID);
            }
            
            // Add any new attachments from the SOAPMessage to this Message
            Iterator it = soapMessage.getAttachments();
            while (it.hasNext()) {
                
                AttachmentPart ap = (AttachmentPart) it.next();
                String cid = ap.getContentId();
                if (log.isDebugEnabled()) {
                    log.debug("  add SOAPMessage attachment to Message.  cid = " + cid);
                }
                addDataHandler(ap.getDataHandler(),  cid);
                dontCopy.add(cid);
            }
            
            // Add the attachments from this Message to the SOAPMessage
            for (String cid:getAttachmentIDs()) {
                DataHandler dh = attachments.getDataHandler(cid);
                if (!dontCopy.contains(cid)) {
                    if (log.isDebugEnabled()) {
                        log.debug("  add Message attachment to SoapMessage.  cid = " + cid);
                    }
                    AttachmentPart ap = MessageUtils.createAttachmentPart(cid, dh, soapMessage);
                    soapMessage.addAttachmentPart(ap);
                }
            }
            
            if (log.isDebugEnabled()) {
                log.debug("  The SOAPMessage has the following attachments");
                Iterator it2 = soapMessage.getAttachments();
                while (it2.hasNext()) {
                    AttachmentPart ap = (AttachmentPart) it2.next();
                    log.debug("    AttachmentPart cid=" + ap.getContentId());
                    log.debug("        contentType =" + ap.getContentType());
                }
            }
            
            if (log.isDebugEnabled()) {
                log.debug("end getAsSOAPMessage");
            }
            return soapMessage;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
        
    }
    
    /**
     * Get the indicated (non-soap part) attachment id
     * @param index
     * @return CID or null if not present
     */
    public String getAttachmentID(int index) {
        List<String> cids = getAttachmentIDs();
        String spCID = getSOAPPartContentID();
        if (log.isDebugEnabled()) {
            log.debug("getAttachmentID for index =" + index);
            for (int i = 0; i < cids.size(); i++) {
                log.debug("Attachment CID (" + i + ") = " + cids.indexOf(i));
            }
            log.debug("The SOAP Part CID is ignored.  It's CID is (" + spCID + ")");
        }
        int spIndex = (spCID == null) ? -1 : cids.indexOf(spCID);
        
        // Bump index so we don't consider the soap part
        index = (spIndex != -1 && spIndex <= index) ? index + 1 : index;
        
        // Return the content id at the calculated index
        String resultCID = null;
        if (index < cids.size()) {
            resultCID = cids.get(index);
        }
        if (log.isDebugEnabled()) {
            log.debug("Returning CID=" + resultCID);
         }
        return resultCID;
    }
    

    public String getAttachmentID(String partName) {
        // Find the prefix that starts with the 
        // partName=
        String prefix = partName + "=";
        List<String> cids = getAttachmentIDs();
        for (String cid: cids) {
            if (cid.startsWith(prefix)) {
                return cid;
            }
        }
        return null;
    }

    
    private String getSOAPPartContentID() {
        String contentID = null;
        if (messageContext == null) {
            return null;  // Attachments set up programmatically...so there is no SOAPPart
        }
        try {
            contentID = attachments.getRootPartContentID();
        } catch (RuntimeException e) {
            // OM will kindly throw an OMException or NPE if the attachments is set up 
            // programmatically. 
            return null;
        }
        return contentID;
    }
    
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Message#getValue(java.lang.Object, 
     * org.apache.axis2.jaxws.message.factory.BlockFactory)
     */
    public Object getValue(Object context, BlockFactory blockFactory) throws WebServiceException {
        try {
            Object value = null;
            if (protocol == Protocol.rest) {
                // The implementation of rest stores the rest xml inside a dummy soap 1.1 envelope.
                // So use the get body block logic.
                Block block = xmlPart.getBodyBlock(context, blockFactory);
                if (block != null) {
                    value = block.getBusinessObject(true);
                }
                
            } else {
                // Must be SOAP
                if (blockFactory instanceof SOAPEnvelopeBlockFactory) {
                    value = getAsSOAPMessage();
                } else {
                    // TODO: This doesn't seem right to me.
                    // We should not have an intermediate StringBlock.
                    // This is not performant. Scheu
                    OMElement messageOM = getAsOMElement();
                    String stringValue = messageOM.toString();
                    String soapNS =
                            (protocol == Protocol.soap11) ? SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE
                                    : SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE;
                    QName soapEnvQname = new QName(soapNS, "Envelope");


                    XMLStringBlockFactory stringFactory =
                            (XMLStringBlockFactory) 
                            FactoryRegistry.getFactory(XMLStringBlockFactory.class);
                    Block stringBlock = stringFactory.createFrom(stringValue, null, soapEnvQname);
                    Block block = blockFactory.createFrom(stringBlock, context);
                    value = block.getBusinessObject(true);
                }
            }
            return value;
        } catch (Throwable e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }
    
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Message#getAttachmentIDs()
     */
    public List<String> getAttachmentIDs() {
        return attachments.getContentIDList();
    }
    
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Message#getDataHandler(java.lang.String)
     */
    public DataHandler getDataHandler(String cid) {
        // if null DH was specified explicitly, just return
        if(cid == null) {
            return (DataHandler) null;
        }
        String bcid = getBlobCID(cid);
        return attachments.getDataHandler(bcid);
    }
    
    
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Message#removeDataHandler(java.lang.String)
     */
    public DataHandler removeDataHandler(String cid) {
        String bcid = getBlobCID(cid);
        DataHandler dh = attachments.getDataHandler(bcid);
        attachments.removeDataHandler(bcid);
        return dh;
    }
    
    private String getBlobCID(String cid) {
        String blobCID = cid;
        if (cid.startsWith("cid:")) {
            blobCID = cid.substring(4);  // Skip over cid:
        }
        return blobCID;
    }
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.XMLPart#getProtocol()
     */
    public Protocol getProtocol() {
        return protocol;
    }
    
    
    public OMElement getAsOMElement() throws WebServiceException {
        return xmlPart.getAsOMElement();
    }
    
    public javax.xml.soap.SOAPEnvelope getAsSOAPEnvelope() throws WebServiceException {
        return xmlPart.getAsSOAPEnvelope();
    }
    
    public Block getBodyBlock(int index, Object context, BlockFactory blockFactory) 
    throws WebServiceException {
        return xmlPart.getBodyBlock(index, context, blockFactory);
    }
    
    public Block getHeaderBlock(String namespace, String localPart, Object context, 
                                BlockFactory blockFactory) 
    throws WebServiceException {
        return xmlPart.getHeaderBlock(namespace, localPart, context, blockFactory);
    }
    
    public List<Block> getHeaderBlocks(String namespace, String localPart, 
                                       Object context, BlockFactory blockFactory, 
                                       RolePlayer rolePlayer) throws WebServiceException {
        return xmlPart.getHeaderBlocks(namespace, localPart, context, blockFactory, rolePlayer);
    }

    public int getNumBodyBlocks() throws WebServiceException {
        return xmlPart.getNumBodyBlocks();
    }
    
    public List<QName> getBodyBlockQNames() throws WebServiceException {
        return xmlPart.getBodyBlockQNames();
    }
    
    public int getNumHeaderBlocks() throws WebServiceException {
        return xmlPart.getNumHeaderBlocks();
    }
    
    public XMLStreamReader getXMLStreamReader(boolean consume) 
    throws WebServiceException {
        return xmlPart.getXMLStreamReader(consume);
    }
    
    public boolean isConsumed() {
        return xmlPart.isConsumed();
    }
    
    public void outputTo(XMLStreamWriter writer, boolean consume) 
    throws XMLStreamException, WebServiceException {
        xmlPart.outputTo(writer, consume);
    }
    
    public void removeBodyBlock(int index) throws WebServiceException {
        xmlPart.removeBodyBlock(index);
    }
    
    public void removeHeaderBlock(String namespace, String localPart) 
    throws WebServiceException {
        xmlPart.removeHeaderBlock(namespace, localPart);
    }
    
    public void setBodyBlock(int index, Block block) 
    throws WebServiceException {
        xmlPart.setBodyBlock(index, block);
    }
    
    public void setHeaderBlock(String namespace, String localPart, Block block) 
    throws WebServiceException {
        xmlPart.setHeaderBlock(namespace, localPart, block);
    }
    
    public void appendHeaderBlock(String namespace, String localPart, Block block) 
    throws WebServiceException {
        xmlPart.appendHeaderBlock(namespace, localPart, block);
    }
    
    public String traceString(String indent) {
        return xmlPart.traceString(indent);
    }
    
    /**
     * Load the SAAJConverter
     * @return SAAJConverter
     */
    SAAJConverter converter = null;
    private SAAJConverter getSAAJConverter() {
        if (converter == null) {
            SAAJConverterFactory factory = (
                    SAAJConverterFactory)FactoryRegistry.getFactory(SAAJConverterFactory.class);
            converter = factory.getSAAJConverter();
        }
        return converter;
    }
    
    public void addDataHandler(DataHandler dh, String id) {
        if (id.startsWith("<")  && id.endsWith(">")) {
            id = id.substring(1, id.length()-1);
        }
        attachments.addDataHandler(id, dh);
    }
    
    public Message getParent() {
        return null;
    }
    
    public void setParent(Message msg) { 
        // A Message does not have a parent
        throw new UnsupportedOperationException();
    }
    
    /**
     * @return true if the binding for this message indicates mtom
     */
    public boolean isMTOMEnabled() {
        // If the message has SWA attachments, this "wins" over the mtom setting.
        return mtomEnabled && !doingSWA;
    }
    
    /**
     * @param true if the binding for this message indicates mtom
     */
    public void setMTOMEnabled(boolean b) {
        mtomEnabled = b;
    }
    
    public XMLFault getXMLFault() throws WebServiceException {
        return xmlPart.getXMLFault();
    }
    
    public void setXMLFault(XMLFault xmlFault) throws WebServiceException {
        xmlPart.setXMLFault(xmlFault);
    }
    
    public boolean isFault() throws WebServiceException {
        return xmlPart.isFault();
    }
    
    public String getXMLPartContentType() {
        return xmlPart.getXMLPartContentType();
    }
    
    public Style getStyle() {
        return xmlPart.getStyle();
    }
    
    public void setStyle(Style style) throws WebServiceException {
        xmlPart.setStyle(style);
    }
    
    public QName getOperationElement() throws WebServiceException {
        return xmlPart.getOperationElement();
    }
    
    public void setOperationElement(QName operationQName) throws WebServiceException {
        xmlPart.setOperationElement(operationQName);
    }
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Attachment#getMimeHeaders()
     */
    public Map getMimeHeaders() {
        // Lazily create transport headers.
        if (transportHeaders == null) {
            transportHeaders = new HashMap();
        }
        return transportHeaders;
     }
    
    /* (non-Javadoc)
     * @see org.apache.axis2.jaxws.message.Attachment#setMimeHeaders(java.util.Map)
     */
    public void setMimeHeaders(Map map) {
        transportHeaders = map;
        if (transportHeaders == null) {
            transportHeaders = new HashMap();
          }
    }
    
    public Block getBodyBlock(Object context, BlockFactory blockFactory) 
    throws WebServiceException {
        return xmlPart.getBodyBlock(context, blockFactory);
    }
    
    public void setBodyBlock(Block block) throws WebServiceException {
        xmlPart.setBodyBlock(block);
    }
    
    public void setPostPivot() {
        this.postPivot = true;
    }
    
    public boolean isPostPivot() {
        return postPivot;
    }
    
    public int getIndirection() {
        return xmlPart.getIndirection();
    }
    
    public void setIndirection(int indirection) {
        xmlPart.setIndirection(indirection);
    }
    
    public MessageContext getMessageContext() {
        return messageContext;
    }
    
    public void setMessageContext(MessageContext messageContext) {
        if (this.messageContext != messageContext) {
            // Copy attachments to the new map
            Attachments newMap = messageContext.getAxisMessageContext().getAttachmentMap();
            Attachments oldMap = attachments;
            for (String cid:oldMap.getAllContentIDs()) {
                DataHandler dh = oldMap.getDataHandler(cid);
                if (dh != null) {
                    newMap.addDataHandler(cid, dh);
                }
            }
            // If not MTOM and there are attachments, set SWA style
            if (!isMTOMEnabled()) {
                String[] cids = newMap.getAllContentIDs();
                if (cids.length > 0) {
                    messageContext.setProperty(Configuration.ENABLE_SWA, "true");
                }
            }
            if (log.isDebugEnabled()) {
                for (String cid:newMap.getAllContentIDs()) {
                    log.debug("Message has an attachment with content id= " + cid);
                }
            }
            attachments = newMap;
        }
        
        // Check for cached attachment file(s) if attachments exist.
        if(attachments != null && !messageContext.getAxisMessageContext().isServerSide()){
        	AttachmentUtils.findCachedAttachment(attachments);
        }
        
        this.messageContext = messageContext;
    }
    public void setDoingSWA(boolean value) {
        doingSWA = value;
    }

    public boolean isDoingSWA() {
        return doingSWA;
    }
    
    public void close() {
        if (xmlPart != null) {
            xmlPart.close();
        }
    }

    public Set<QName> getHeaderQNames() {
        return (xmlPart == null) ? null : xmlPart.getHeaderQNames();     
    }

}
