/*
 * 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.commons.mail;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;

/**
 * An HTML multipart email.
 *
 * <p>This class is used to send HTML formatted email.  A text message
 * can also be set for HTML unaware email clients, such as text-based
 * email clients.
 *
 * <p>This class also inherits from {@link MultiPartEmail}, so it is easy to
 * add attachments to the email.
 *
 * <p>To send an email in HTML, one should create a <code>HtmlEmail</code>, then
 * use the {@link #setFrom(String)}, {@link #addTo(String)} etc. methods.
 * The HTML content can be set with the {@link #setHtmlMsg(String)} method. The
 * alternative text content can be set with {@link #setTextMsg(String)}.
 *
 * <p>Either the text or HTML can be omitted, in which case the "main"
 * part of the multipart becomes whichever is supplied rather than a
 * <code>multipart/alternative</code>.
 *
 * <h3>Embedding Images and Media</h3>
 *
 * <p>It is also possible to embed URLs, files, or arbitrary
 * <code>DataSource</code>s directly into the body of the mail:
 * <pre>
 * HtmlEmail he = new HtmlEmail();
 * File img = new File("my/image.gif");
 * PNGDataSource png = new PNGDataSource(decodedPNGOutputStream); // a custom class
 * StringBuffer msg = new StringBuffer();
 * msg.append("&lt;html&gt;&lt;body&gt;");
 * msg.append("&lt;img src=cid:").append(he.embed(img)).append("&gt;");
 * msg.append("&lt;img src=cid:").append(he.embed(png)).append("&gt;");
 * msg.append("&lt;/body&gt;&lt;/html&gt;");
 * he.setHtmlMsg(msg.toString());
 * // code to set the other email fields (not shown)
 * </pre>
 *
 * <p>Embedded entities are tracked by their name, which for <code>File</code>s is
 * the file name itself and for <code>URL</code>s is the canonical path. It is
 * an error to bind the same name to more than one entity, and this class will
 * attempt to validate that for <code>File</code>s and <code>URL</code>s. When
 * embedding a <code>DataSource</code>, the code uses the <code>equals()</code>
 * method defined on the <code>DataSource</code>s to make the determination.
 *
 * @since 1.0
 */
public class HtmlEmail extends MultiPartEmail
{
    /** Definition of the length of generated CID's. */
    public static final int CID_LENGTH = 10;

    /** prefix for default HTML mail. */
    private static final String HTML_MESSAGE_START = "<html><body><pre>";
    /** suffix for default HTML mail. */
    private static final String HTML_MESSAGE_END = "</pre></body></html>";


    /**
     * Text part of the message. This will be used as alternative text if
     * the email client does not support HTML messages.
     */
    protected String text;

    /** Html part of the message. */
    protected String html;

    /**
     * @deprecated As of commons-email 1.1, no longer used. Inline embedded
     * objects are now stored in {@link #inlineEmbeds}.
     */
    @Deprecated
    protected List<InlineImage> inlineImages;

    /**
     * Embedded images Map&lt;String, InlineImage&gt; where the key is the
     * user-defined image name.
     */
    protected Map<String, InlineImage> inlineEmbeds = new HashMap<String, InlineImage>();

    /**
     * Set the text content.
     *
     * @param aText A String.
     * @return An HtmlEmail.
     * @throws EmailException see javax.mail.internet.MimeBodyPart
     *  for definitions
     * @since 1.0
     */
    public HtmlEmail setTextMsg(final String aText) throws EmailException
    {
        if (EmailUtils.isEmpty(aText))
        {
            throw new EmailException("Invalid message supplied");
        }

        this.text = aText;
        return this;
    }

    /**
     * Set the HTML content.
     *
     * @param aHtml A String.
     * @return An HtmlEmail.
     * @throws EmailException see javax.mail.internet.MimeBodyPart
     *  for definitions
     * @since 1.0
     */
    public HtmlEmail setHtmlMsg(final String aHtml) throws EmailException
    {
        if (EmailUtils.isEmpty(aHtml))
        {
            throw new EmailException("Invalid message supplied");
        }

        this.html = aHtml;
        return this;
    }

    /**
     * Set the message.
     *
     * <p>This method overrides {@link MultiPartEmail#setMsg(String)} in
     * order to send an HTML message instead of a plain text message in
     * the mail body. The message is formatted in HTML for the HTML
     * part of the message; it is left as is in the alternate text
     * part.
     *
     * @param msg the message text to use
     * @return this <code>HtmlEmail</code>
     * @throws EmailException if msg is null or empty;
     * see javax.mail.internet.MimeBodyPart for definitions
     * @since 1.0
     */
    @Override
    public Email setMsg(final String msg) throws EmailException
    {
        if (EmailUtils.isEmpty(msg))
        {
            throw new EmailException("Invalid message supplied");
        }

        setTextMsg(msg);

        final StringBuffer htmlMsgBuf = new StringBuffer(
            msg.length()
            + HTML_MESSAGE_START.length()
            + HTML_MESSAGE_END.length()
        );

        htmlMsgBuf.append(HTML_MESSAGE_START)
            .append(msg)
            .append(HTML_MESSAGE_END);

        setHtmlMsg(htmlMsgBuf.toString());

        return this;
    }

    /**
     * Attempts to parse the specified <code>String</code> as a URL that will
     * then be embedded in the message.
     *
     * @param urlString String representation of the URL.
     * @param name The name that will be set in the file name header field.
     * @return A String with the Content-ID of the URL.
     * @throws EmailException when URL supplied is invalid or if {@code name} is null
     * or empty; also see {@link javax.mail.internet.MimeBodyPart} for definitions
     *
     * @see #embed(URL, String)
     * @since 1.1
     */
    public String embed(final String urlString, final String name) throws EmailException
    {
        try
        {
            return embed(new URL(urlString), name);
        }
        catch (final MalformedURLException e)
        {
            throw new EmailException("Invalid URL", e);
        }
    }

    /**
     * Embeds an URL in the HTML.
     *
     * <p>This method embeds a file located by an URL into
     * the mail body. It allows, for instance, to add inline images
     * to the email.  Inline files may be referenced with a
     * <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
     * returned by the embed function. It is an error to bind the same name
     * to more than one URL; if the same URL is embedded multiple times, the
     * same Content-ID is guaranteed to be returned.
     *
     * <p>While functionally the same as passing <code>URLDataSource</code> to
     * {@link #embed(DataSource, String, String)}, this method attempts
     * to validate the URL before embedding it in the message and will throw
     * <code>EmailException</code> if the validation fails. In this case, the
     * <code>HtmlEmail</code> object will not be changed.
     *
     * <p>
     * NOTE: Clients should take care to ensure that different URLs are bound to
     * different names. This implementation tries to detect this and throw
     * <code>EmailException</code>. However, it is not guaranteed to catch
     * all cases, especially when the URL refers to a remote HTTP host that
     * may be part of a virtual host cluster.
     *
     * @param url The URL of the file.
     * @param name The name that will be set in the file name header
     * field.
     * @return A String with the Content-ID of the file.
     * @throws EmailException when URL supplied is invalid or if {@code name} is null
     * or empty; also see {@link javax.mail.internet.MimeBodyPart} for definitions
     * @since 1.0
     */
    public String embed(final URL url, final String name) throws EmailException
    {
        if (EmailUtils.isEmpty(name))
        {
            throw new EmailException("name cannot be null or empty");
        }

        // check if a URLDataSource for this name has already been attached;
        // if so, return the cached CID value.
        if (inlineEmbeds.containsKey(name))
        {
            final InlineImage ii = inlineEmbeds.get(name);
            final URLDataSource urlDataSource = (URLDataSource) ii.getDataSource();
            // make sure the supplied URL points to the same thing
            // as the one already associated with this name.
            // NOTE: Comparing URLs with URL.equals() is a blocking operation
            // in the case of a network failure therefore we use
            // url.toExternalForm().equals() here.
            if (url.toExternalForm().equals(urlDataSource.getURL().toExternalForm()))
            {
                return ii.getCid();
            }
            throw new EmailException("embedded name '" + name
                + "' is already bound to URL " + urlDataSource.getURL()
                + "; existing names cannot be rebound");
        }

        // verify that the URL is valid
        InputStream is = null;
        try
        {
            is = url.openStream();
        }
        catch (final IOException e)
        {
            throw new EmailException("Invalid URL", e);
        }
        finally
        {
            try
            {
                if (is != null)
                {
                    is.close();
                }
            }
            catch (final IOException ioe) // NOPMD
            { /* sigh */ }
        }

        return embed(new URLDataSource(url), name);
    }

    /**
     * Embeds a file in the HTML. This implementation delegates to
     * {@link #embed(File, String)}.
     *
     * @param file The <code>File</code> object to embed
     * @return A String with the Content-ID of the file.
     * @throws EmailException when the supplied <code>File</code> cannot be
     * used; also see {@link javax.mail.internet.MimeBodyPart} for definitions
     *
     * @see #embed(File, String)
     * @since 1.1
     */
    public String embed(final File file) throws EmailException
    {
        final String cid = EmailUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase(Locale.ENGLISH);
        return embed(file, cid);
    }

    /**
     * Embeds a file in the HTML.
     *
     * <p>This method embeds a file located by an URL into
     * the mail body. It allows, for instance, to add inline images
     * to the email.  Inline files may be referenced with a
     * <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
     * returned by the embed function. Files are bound to their names, which is
     * the value returned by {@link java.io.File#getName()}. If the same file
     * is embedded multiple times, the same CID is guaranteed to be returned.
     *
     * <p>While functionally the same as passing <code>FileDataSource</code> to
     * {@link #embed(DataSource, String, String)}, this method attempts
     * to validate the file before embedding it in the message and will throw
     * <code>EmailException</code> if the validation fails. In this case, the
     * <code>HtmlEmail</code> object will not be changed.
     *
     * @param file The <code>File</code> to embed
     * @param cid the Content-ID to use for the embedded <code>File</code>
     * @return A String with the Content-ID of the file.
     * @throws EmailException when the supplied <code>File</code> cannot be used
     *  or if the file has already been embedded;
     *  also see {@link javax.mail.internet.MimeBodyPart} for definitions
     * @since 1.1
     */
    public String embed(final File file, final String cid) throws EmailException
    {
        if (EmailUtils.isEmpty(file.getName()))
        {
            throw new EmailException("file name cannot be null or empty");
        }

        // verify that the File can provide a canonical path
        String filePath = null;
        try
        {
            filePath = file.getCanonicalPath();
        }
        catch (final IOException ioe)
        {
            throw new EmailException("couldn't get canonical path for "
                    + file.getName(), ioe);
        }

        // check if a FileDataSource for this name has already been attached;
        // if so, return the cached CID value.
        if (inlineEmbeds.containsKey(file.getName()))
        {
            final InlineImage ii = inlineEmbeds.get(file.getName());
            final FileDataSource fileDataSource = (FileDataSource) ii.getDataSource();
            // make sure the supplied file has the same canonical path
            // as the one already associated with this name.
            String existingFilePath = null;
            try
            {
                existingFilePath = fileDataSource.getFile().getCanonicalPath();
            }
            catch (final IOException ioe)
            {
                throw new EmailException("couldn't get canonical path for file "
                        + fileDataSource.getFile().getName()
                        + "which has already been embedded", ioe);
            }
            if (filePath.equals(existingFilePath))
            {
                return ii.getCid();
            }
            throw new EmailException("embedded name '" + file.getName()
                + "' is already bound to file " + existingFilePath
                + "; existing names cannot be rebound");
        }

        // verify that the file is valid
        if (!file.exists())
        {
            throw new EmailException("file " + filePath + " doesn't exist");
        }
        if (!file.isFile())
        {
            throw new EmailException("file " + filePath + " isn't a normal file");
        }
        if (!file.canRead())
        {
            throw new EmailException("file " + filePath + " isn't readable");
        }

        return embed(new FileDataSource(file), file.getName(), cid);
    }

    /**
     * Embeds the specified <code>DataSource</code> in the HTML using a
     * randomly generated Content-ID. Returns the generated Content-ID string.
     *
     * @param dataSource the <code>DataSource</code> to embed
     * @param name the name that will be set in the file name header field
     * @return the generated Content-ID for this <code>DataSource</code>
     * @throws EmailException if the embedding fails or if <code>name</code> is
     * null or empty
     * @see #embed(DataSource, String, String)
     * @since 1.1
     */
    public String embed(final DataSource dataSource, final String name) throws EmailException
    {
        // check if the DataSource has already been attached;
        // if so, return the cached CID value.
        if (inlineEmbeds.containsKey(name))
        {
            final InlineImage ii = inlineEmbeds.get(name);
            // make sure the supplied URL points to the same thing
            // as the one already associated with this name.
            if (dataSource.equals(ii.getDataSource()))
            {
                return ii.getCid();
            }
            throw new EmailException("embedded DataSource '" + name
                + "' is already bound to name " + ii.getDataSource().toString()
                + "; existing names cannot be rebound");
        }

        final String cid = EmailUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase();
        return embed(dataSource, name, cid);
    }

    /**
     * Embeds the specified <code>DataSource</code> in the HTML using the
     * specified Content-ID. Returns the specified Content-ID string.
     *
     * @param dataSource the <code>DataSource</code> to embed
     * @param name the name that will be set in the file name header field
     * @param cid the Content-ID to use for this <code>DataSource</code>
     * @return the URL encoded Content-ID for this <code>DataSource</code>
     * @throws EmailException if the embedding fails or if <code>name</code> is
     * null or empty
     * @since 1.1
     */
    public String embed(final DataSource dataSource, final String name, final String cid)
        throws EmailException
    {
        if (EmailUtils.isEmpty(name))
        {
            throw new EmailException("name cannot be null or empty");
        }

        final MimeBodyPart mbp = new MimeBodyPart();

        try
        {
            // URL encode the cid according to RFC 2392
            final String encodedCid = EmailUtils.encodeUrl(cid);

            mbp.setDataHandler(new DataHandler(dataSource));
            mbp.setFileName(name);
            mbp.setDisposition(EmailAttachment.INLINE);
            mbp.setContentID("<" + encodedCid + ">");

            final InlineImage ii = new InlineImage(encodedCid, dataSource, mbp);
            this.inlineEmbeds.put(name, ii);

            return encodedCid;
        }
        catch (final MessagingException me)
        {
            throw new EmailException(me);
        }
        catch (final UnsupportedEncodingException uee)
        {
            throw new EmailException(uee);
        }
    }

    /**
     * Does the work of actually building the MimeMessage. Please note that
     * a user rarely calls this method directly and only if he/she is
     * interested in the sending the underlying MimeMessage without
     * commons-email.
     *
     * @throws EmailException if there was an error.
     * @since 1.0
     */
    @Override
    public void buildMimeMessage() throws EmailException
    {
        try
        {
            build();
        }
        catch (final MessagingException me)
        {
            throw new EmailException(me);
        }
        super.buildMimeMessage();
    }

    /**
     * @throws EmailException EmailException
     * @throws MessagingException MessagingException
     */
    private void build() throws MessagingException, EmailException
    {
        final MimeMultipart rootContainer = this.getContainer();
        MimeMultipart bodyEmbedsContainer = rootContainer;
        MimeMultipart bodyContainer = rootContainer;
        MimeBodyPart msgHtml = null;
        MimeBodyPart msgText = null;

        rootContainer.setSubType("mixed");

        // determine how to form multiparts of email

        if (EmailUtils.isNotEmpty(this.html) && this.inlineEmbeds.size() > 0)
        {
            //If HTML body and embeds are used, create a related container and add it to the root container
            bodyEmbedsContainer = new MimeMultipart("related");
            bodyContainer = bodyEmbedsContainer;
            this.addPart(bodyEmbedsContainer, 0);

            // If TEXT body was specified, create a alternative container and add it to the embeds container
            if (EmailUtils.isNotEmpty(this.text))
            {
                bodyContainer = new MimeMultipart("alternative");
                final BodyPart bodyPart = createBodyPart();
                try
                {
                    bodyPart.setContent(bodyContainer);
                    bodyEmbedsContainer.addBodyPart(bodyPart, 0);
                }
                catch (final MessagingException me)
                {
                    throw new EmailException(me);
                }
            }
        }
        else if (EmailUtils.isNotEmpty(this.text) && EmailUtils.isNotEmpty(this.html))
        {
            // EMAIL-142: if we have both an HTML and TEXT body, but no attachments or
            //            inline images, the root container should have mimetype
            //            "multipart/alternative".
            // reference: http://tools.ietf.org/html/rfc2046#section-5.1.4
            if (this.inlineEmbeds.size() > 0 || isBoolHasAttachments())
            {
                // If both HTML and TEXT bodies are provided, create an alternative
                // container and add it to the root container
                bodyContainer = new MimeMultipart("alternative");
                this.addPart(bodyContainer, 0);
            }
            else
            {
                // no attachments or embedded images present, change the mimetype
                // of the root container (= body container)
                rootContainer.setSubType("alternative");
            }
        }

        if (EmailUtils.isNotEmpty(this.html))
        {
            msgHtml = new MimeBodyPart();
            bodyContainer.addBodyPart(msgHtml, 0);

            // EMAIL-104: call explicitly setText to use default mime charset
            //            (property "mail.mime.charset") in case none has been set
            msgHtml.setText(this.html, this.charset, EmailConstants.TEXT_SUBTYPE_HTML);

            // EMAIL-147: work-around for buggy JavaMail implementations;
            //            in case setText(...) does not set the correct content type,
            //            use the setContent() method instead.
            final String contentType = msgHtml.getContentType();
            if (contentType == null || !contentType.equals(EmailConstants.TEXT_HTML))
            {
                // apply default charset if one has been set
                if (EmailUtils.isNotEmpty(this.charset))
                {
                    msgHtml.setContent(this.html, EmailConstants.TEXT_HTML + "; charset=" + this.charset);
                }
                else
                {
                    // unfortunately, MimeUtility.getDefaultMIMECharset() is package private
                    // and thus can not be used to set the default system charset in case
                    // no charset has been provided by the user
                    msgHtml.setContent(this.html, EmailConstants.TEXT_HTML);
                }
            }

            for (final InlineImage image : this.inlineEmbeds.values())
            {
                bodyEmbedsContainer.addBodyPart(image.getMbp());
            }
        }

        if (EmailUtils.isNotEmpty(this.text))
        {
            msgText = new MimeBodyPart();
            bodyContainer.addBodyPart(msgText, 0);

            // EMAIL-104: call explicitly setText to use default mime charset
            //            (property "mail.mime.charset") in case none has been set
            msgText.setText(this.text, this.charset);
        }
    }

    /**
     * Private bean class that encapsulates data about URL contents
     * that are embedded in the final email.
     * @since 1.1
     */
    private static class InlineImage
    {
        /** content id. */
        private final String cid;
        /** <code>DataSource</code> for the content. */
        private final DataSource dataSource;
        /** the <code>MimeBodyPart</code> that contains the encoded data. */
        private final MimeBodyPart mbp;

        /**
         * Creates an InlineImage object to represent the
         * specified content ID and <code>MimeBodyPart</code>.
         * @param cid the generated content ID
         * @param dataSource the <code>DataSource</code> that represents the content
         * @param mbp the <code>MimeBodyPart</code> that contains the encoded
         * data
         */
        public InlineImage(final String cid, final DataSource dataSource, final MimeBodyPart mbp)
        {
            this.cid = cid;
            this.dataSource = dataSource;
            this.mbp = mbp;
        }

        /**
         * Returns the unique content ID of this InlineImage.
         * @return the unique content ID of this InlineImage
         */
        public String getCid()
        {
            return cid;
        }

        /**
         * Returns the <code>DataSource</code> that represents the encoded content.
         * @return the <code>DataSource</code> representing the encoded content
         */
        public DataSource getDataSource()
        {
            return dataSource;
        }

        /**
         * Returns the <code>MimeBodyPart</code> that contains the
         * encoded InlineImage data.
         * @return the <code>MimeBodyPart</code> containing the encoded
         * InlineImage data
         */
        public MimeBodyPart getMbp()
        {
            return mbp;
        }

        // equals()/hashCode() implementations, since this class
        // is stored as a entry in a Map.
        /**
         * {@inheritDoc}
         * @return true if the other object is also an InlineImage with the same cid.
         */
        @Override
        public boolean equals(final Object obj)
        {
            if (this == obj)
            {
                return true;
            }
            if (!(obj instanceof InlineImage))
            {
                return false;
            }

            final InlineImage that = (InlineImage) obj;

            return this.cid.equals(that.cid);
        }

        /**
         * {@inheritDoc}
         * @return the cid hashCode.
         */
        @Override
        public int hashCode()
        {
            return cid.hashCode();
        }
    }
}
