/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed 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.saaj;

import org.apache.axiom.om.OMOutputFormat;
import org.apache.axis2.transport.http.HTTPConstants;

import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

public class SOAPMessageImpl extends SOAPMessage {

    private SOAPPart soapPart;
    private Collection attachmentParts = new ArrayList();
    private MimeHeadersEx mimeHeaders;

    private Map props = new Hashtable();
    private boolean saveRequired;

    public SOAPMessageImpl(SOAPEnvelopeImpl soapEnvelope) {
        String contentType = null;
        if (mimeHeaders != null) {
            String contentTypes[] = mimeHeaders.getHeader("Content-Type");
            contentType = (contentTypes != null) ? contentTypes[0] : null;
        }

        setCharsetEncoding(contentType);

        soapPart = new SOAPPartImpl(this, soapEnvelope);

        this.mimeHeaders = new MimeHeadersEx();
    }

    public SOAPMessageImpl(InputStream inputstream,
                           javax.xml.soap.MimeHeaders mimeHeaders) throws SOAPException {
        String contentType = null;
        if (mimeHeaders != null) {
            String contentTypes[] = mimeHeaders.getHeader("Content-Type");
            contentType = (contentTypes != null) ? contentTypes[0] : null;
        }

        setCharsetEncoding(contentType);
        if (contentType != null && contentType.indexOf("multipart/related;") == 0) {
//            soapPart = new SOAPPartImpl(this, inputstream, mimeHeaders);
        } else {
            soapPart = new SOAPPartImpl(this, inputstream);
        }

        this.mimeHeaders = (mimeHeaders == null) ?
                           new MimeHeadersEx() :
                           new MimeHeadersEx(mimeHeaders);
    }

    /**
     * Retrieves a description of this <CODE>SOAPMessage</CODE>
     * object's content.
     *
     * @return a <CODE>String</CODE> describing the content of this
     *         message or <CODE>null</CODE> if no description has been
     *         set
     * @see #setContentDescription(java.lang.String) setContentDescription(java.lang.String)
     */
    public String getContentDescription() {
        String values[] = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION);
        if (values != null && values.length > 0) {
            return values[0];
        }
        return null;
    }

    /**
     * Sets the description of this <CODE>SOAPMessage</CODE>
     * object's content with the given description.
     *
     * @param description a <CODE>String</CODE>
     *                    describing the content of this message
     * @see #getContentDescription() getContentDescription()
     */
    public void setContentDescription(String description) {
        mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION, description);
    }

    /**
     * Gets the SOAP part of this <CODE>SOAPMessage</CODE> object.
     * <p/>
     * <p/>
     * <P>If a <CODE>SOAPMessage</CODE> object contains one or
     * more attachments, the SOAP Part must be the first MIME body
     * part in the message.</P>
     *
     * @return the <CODE>SOAPPart</CODE> object for this <CODE>
     *         SOAPMessage</CODE> object
     */
    public SOAPPart getSOAPPart() {
        return soapPart;
    }

    /**
     * Removes all <CODE>AttachmentPart</CODE> objects that have
     * been added to this <CODE>SOAPMessage</CODE> object.
     * <p/>
     * <P>This method does not touch the SOAP part.</P>
     */
    public void removeAllAttachments() {
        attachmentParts.clear();
    }

    /**
     * Gets a count of the number of attachments in this
     * message. This count does not include the SOAP part.
     *
     * @return the number of <CODE>AttachmentPart</CODE> objects
     *         that are part of this <CODE>SOAPMessage</CODE>
     *         object
     */
    public int countAttachments() {
        return attachmentParts.size();
    }

    /**
     * Retrieves all the <CODE>AttachmentPart</CODE> objects
     * that are part of this <CODE>SOAPMessage</CODE> object.
     *
     * @return an iterator over all the attachments in this
     *         message
     */
    public Iterator getAttachments() {
        return attachmentParts.iterator();
    }

    /**
     * Retrieves all the AttachmentPart objects that have header entries that match the specified
     * headers.
     * Note that a returned attachment could have headers in addition to those specified.
     *
     * @param headers a {@link javax.xml.soap.MimeHeaders}
     *                object containing the MIME headers for which to search
     * @return an iterator over all attachments({@link javax.xml.soap.AttachmentPart})
     *         that have a header that matches one of the given headers
     */
    public Iterator getAttachments(javax.xml.soap.MimeHeaders headers) {
        Collection matchingAttachmentParts = new ArrayList();
        Iterator iterator = getAttachments();
        {
            AttachmentPartImpl part;
            while (iterator.hasNext()) {
                part = (AttachmentPartImpl) iterator.next();
                if (part.matches(headers)) {
                    matchingAttachmentParts.add(part);
                }
            }
        }
        return matchingAttachmentParts.iterator();
    }

    /**
     * Adds the given <CODE>AttachmentPart</CODE> object to this
     * <CODE>SOAPMessage</CODE> object. An <CODE>
     * AttachmentPart</CODE> object must be created before it can be
     * added to a message.
     *
     * @param attachmentPart an <CODE>
     *                       AttachmentPart</CODE> object that is to become part of
     *                       this <CODE>SOAPMessage</CODE> object
     * @throws java.lang.IllegalArgumentException
     *
     */
    public void addAttachmentPart(AttachmentPart attachmentPart) {
        if (attachmentPart != null) {
            attachmentParts.add(attachmentPart);
            mimeHeaders.setHeader("Content-Type", "multipart/related");
        }
    }

    /**
     * Creates a new empty <CODE>AttachmentPart</CODE> object.
     * Note that the method <CODE>addAttachmentPart</CODE> must be
     * called with this new <CODE>AttachmentPart</CODE> object as
     * the parameter in order for it to become an attachment to this
     * <CODE>SOAPMessage</CODE> object.
     *
     * @return a new <CODE>AttachmentPart</CODE> object that can be
     *         populated and added to this <CODE>SOAPMessage</CODE>
     *         object
     */
    public AttachmentPart createAttachmentPart() {
        return new AttachmentPartImpl();
    }

    /**
     * Returns all the transport-specific MIME headers for this
     * <CODE>SOAPMessage</CODE> object in a transport-independent
     * fashion.
     *
     * @return a <CODE>MimeHeaders</CODE> object containing the
     *         <CODE>MimeHeader</CODE> objects
     */
    public javax.xml.soap.MimeHeaders getMimeHeaders() {
        return mimeHeaders;
    }

    /**
     * Updates this <CODE>SOAPMessage</CODE> object with all the
     * changes that have been made to it. This method is called
     * automatically when a message is sent or written to by the
     * methods <CODE>ProviderConnection.send</CODE>, <CODE>
     * SOAPConnection.call</CODE>, or <CODE>
     * SOAPMessage.writeTo</CODE>. However, if changes are made to
     * a message that was received or to one that has already been
     * sent, the method <CODE>saveChanges</CODE> needs to be
     * called explicitly in order to save the changes. The method
     * <CODE>saveChanges</CODE> also generates any changes that
     * can be read back (for example, a MessageId in profiles that
     * support a message id). All MIME headers in a message that
     * is created for sending purposes are guaranteed to have
     * valid values only after <CODE>saveChanges</CODE> has been
     * called.
     * <p/>
     * <P>In addition, this method marks the point at which the
     * data from all constituent <CODE>AttachmentPart</CODE>
     * objects are pulled into the message.</P>
     *
     * @throws SOAPException if there was a problem saving changes to this message.
     */
    public void saveChanges() throws SOAPException {
        saveRequired = false;
        // TODO not sure of the implementation
    }

    public void setSaveRequired() {
        this.saveRequired = true;
    }

    /**
     * Indicates whether this <CODE>SOAPMessage</CODE> object
     * has had the method {@link #saveChanges()} called on
     * it.
     *
     * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has
     *         been called on this message at least once; <CODE>
     *         false</CODE> otherwise.
     */
    public boolean saveRequired() {
        return saveRequired;
    }

    /**
     * Writes this <CODE>SOAPMessage</CODE> object to the given
     * output stream. The externalization format is as defined by
     * the SOAP 1.1 with Attachments specification.
     * <p/>
     * <P>If there are no attachments, just an XML stream is
     * written out. For those messages that have attachments,
     * <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
     *
     * @param out the <CODE>OutputStream</CODE>
     *            object to which this <CODE>SOAPMessage</CODE> object will
     *            be written
     * @throws SOAPException if there was a problem in externalizing this SOAP message
     * @throws IOException   if an I/O error occurs
     */
    public void writeTo(OutputStream out) throws SOAPException, IOException {
        try {
            OMOutputFormat format = new OMOutputFormat();
            format.setCharSetEncoding((String) getProperty(CHARACTER_SET_ENCODING));
            String writeXmlDecl = (String) getProperty(WRITE_XML_DECLARATION);
            if (writeXmlDecl == null || writeXmlDecl.equals("false")) {

                //SAAJ default case doesn't send XML decl
                format.setIgnoreXMLDeclaration(true);
            }

            //the writeTo method forces the elements to be built!!!
            ((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMEnvelope().serialize(out, format);
            saveChanges();
        } catch (Exception e) {
            throw new SOAPException(e);
        }
    }

    /**
     * Associates the specified value with the specified property. If there was
     * already a value associated with this property, the old value is replaced.
     * <p/>
     * The valid property names include <code>WRITE_XML_DECLARATION</code> and
     * <code>CHARACTER_SET_ENCODING</code>. All of these standard SAAJ
     * properties are prefixed by "javax.xml.soap". Vendors may also add
     * implementation specific properties. These properties must be prefixed
     * with package names that are unique to the vendor.
     * <p/>
     * Setting the property <code>WRITE_XML_DECLARATION</code> to
     * <code>"true"</code> will cause an XML Declaration to be written out at
     * the start of the SOAP message. The default value of "false" suppresses
     * this declaration.
     * <p/>
     * The property <code>CHARACTER_SET_ENCODING</code> defaults to the value
     * <code>"utf-8"</code> which causes the SOAP message to be encoded using
     * UTF-8. Setting <code>CHARACTER_SET_ENCODING</code> to
     * <code>"utf-16"</code> causes the SOAP message to be encoded using UTF-16.
     * <p/>
     * Some implementations may allow encodings in addition to UTF-8 and UTF-16.
     * Refer to your vendor's documentation for details.
     *
     * @param property the property with which the specified value is to be
     *                 associated
     * @param value    the value
     *                 to be associated with the specified property
     */
    public void setProperty(String property, Object value) {
        props.put(property, value);
    }

    /**
     * Retrieves value of the specified property.
     *
     * @param property the name of the property to retrieve
     * @return the value of the property or <code>null</code> if no such
     *         property exists
     * @throws SOAPException if the property name is not recognized
     */
    public Object getProperty(String property) throws SOAPException {
        return props.get(property);
    }

    /**
     * Gets the SOAP Header contained in this <code>SOAPMessage</code> object.
     *
     * @return the <code>SOAPHeader</code> object contained by this
     *         <code>SOAPMessage</code> object
     * @throws javax.xml.soap.SOAPException if the SOAP Header does not exist or cannot be
     *                                      retrieved
     */
    public SOAPHeader getSOAPHeader() throws SOAPException {
        return this.soapPart.getEnvelope().getHeader();
    }

    /**
     * Gets the SOAP Body contained in this <code>SOAPMessage</code> object.
     *
     * @return the <code>SOAPBody</code> object contained by this
     *         <code>SOAPMessage</code> object
     * @throws javax.xml.soap.SOAPException if the SOAP Body does not exist or cannot be
     *                                      retrieved
     */
    public SOAPBody getSOAPBody() throws SOAPException {
        return this.soapPart.getEnvelope().getBody();
    }

    /**
     * Set the character encoding based on the <code>contentType</code> parameter
     *
     * @param contentType
     */
    private void setCharsetEncoding(final String contentType) {
        if (contentType != null) {
            int delimiterIndex = contentType.lastIndexOf("charset");
            if (delimiterIndex > 0) {
                String charsetPart = contentType.substring(delimiterIndex);
                int charsetIndex = charsetPart.indexOf('=');
                String charset = charsetPart.substring(charsetIndex + 1).trim();
                if ((charset.startsWith("\"") || charset.startsWith("\'"))) {
                    charset = charset.substring(1, charset.length());
                }
                if ((charset.endsWith("\"") || charset.endsWith("\'"))) {
                    charset = charset.substring(0, charset.length() - 1);
                }
                setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
            }
        }
    }
}
