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

import org.apache.axis2.transport.base.*;
import org.apache.commons.logging.LogFactory;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.*;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.kernel.OutTransportInfo;
import org.apache.axis2.kernel.MessageFormatter;
import org.apache.axiom.mime.ContentType;
import org.apache.axiom.om.OMOutputFormat;

import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import javax.activation.DataHandler;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.io.IOException;
import java.text.ParseException;

/**
 * The mail transport sender sends mail using an SMTP server configuration defined
 * in the axis2.xml's transport sender definition
 */

public class MailTransportSender extends AbstractTransportSender
    implements ManagementSupport {

    private String smtpUsername = null;
    private String smtpPassword = null;
    /** Default from address for outgoing messages */
    private InternetAddress smtpFromAddress = null;
    /** A set of custom Bcc address for all outgoing messages */
    private InternetAddress[] smtpBccAddresses = null;
    /** Default mail format */
    private String defaultMailFormat = "Text";
    /** The default Session which can be safely shared */
    private Session session = null;

    /**
     * The public constructor
     */
    public MailTransportSender() {
        log = LogFactory.getLog(MailTransportSender.class);
    }

    /**
     * Initialize the Mail sender and be ready to send messages
     * @param cfgCtx the axis2 configuration context
     * @param transportOut the transport-out description
     * @throws org.apache.axis2.AxisFault on error
     */
    public void init(ConfigurationContext cfgCtx, TransportOutDescription transportOut) throws AxisFault {
        super.init(cfgCtx, transportOut);

        // initialize SMTP session
        Properties props = new Properties();
        List<Parameter> params = transportOut.getParameters();
        for (Parameter p : params) {
            props.put(p.getName(), p.getValue());
        }

        if (props.containsKey(MailConstants.MAIL_SMTP_FROM)) {
            try {
                smtpFromAddress = new InternetAddress(
                    (String) props.get(MailConstants.MAIL_SMTP_FROM));
            } catch (AddressException e) {
                handleException("Invalid default 'From' address : " +
                    props.get(MailConstants.MAIL_SMTP_FROM), e);
            }
        }

        if (props.containsKey(MailConstants.MAIL_SMTP_BCC)) {
            try {
                smtpBccAddresses = InternetAddress.parse(
                    (String) props.get(MailConstants.MAIL_SMTP_BCC));
            } catch (AddressException e) {
                handleException("Invalid default 'Bcc' address : " +
                    props.get(MailConstants.MAIL_SMTP_BCC), e);
            }
        }

        if (props.containsKey(MailConstants.TRANSPORT_MAIL_FORMAT)) {
            defaultMailFormat = (String) props.get(MailConstants.TRANSPORT_MAIL_FORMAT);
        }

        smtpUsername = (String) props.get(MailConstants.MAIL_SMTP_USERNAME);
        smtpPassword = (String) props.get(MailConstants.MAIL_SMTP_PASSWORD);

        if (smtpUsername != null && smtpPassword != null) {
            session = Session.getInstance(props, new Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(smtpUsername, smtpPassword);    
                }
            });
        } else {
            session = Session.getInstance(props, null);
        }

        MailUtils.setupLogging(session, log, transportOut);

        // set the synchronise callback table
        if (cfgCtx.getProperty(BaseConstants.CALLBACK_TABLE) == null){
            cfgCtx.setProperty(BaseConstants.CALLBACK_TABLE, new ConcurrentHashMap());
        }
    }

    /**
     * Send the given message over the Mail transport
     *
     * @param msgCtx the axis2 message context
     * @throws AxisFault on error
     */
    public void sendMessage(MessageContext msgCtx, String targetAddress,
        OutTransportInfo outTransportInfo) throws AxisFault {

        MailOutTransportInfo mailOutInfo = null;

        if (targetAddress != null) {
            if (targetAddress.startsWith(MailConstants.TRANSPORT_NAME)) {
                targetAddress = targetAddress.substring(MailConstants.TRANSPORT_NAME.length()+1);
            }

            if (msgCtx.getReplyTo() != null &&
                !AddressingConstants.Final.WSA_NONE_URI.equals(msgCtx.getReplyTo().getAddress()) &&
                !AddressingConstants.Final.WSA_ANONYMOUS_URL.equals(msgCtx.getReplyTo().getAddress())) {
                
                String replyTo = msgCtx.getReplyTo().getAddress();
                if (replyTo.startsWith(MailConstants.TRANSPORT_NAME)) {
                    replyTo = replyTo.substring(MailConstants.TRANSPORT_NAME.length()+1);
                }
                try {
                    mailOutInfo = new MailOutTransportInfo(new InternetAddress(replyTo));
                } catch (AddressException e) {
                    handleException("Invalid reply address/es : " + replyTo, e);
                }
            } else {
                mailOutInfo = new MailOutTransportInfo(smtpFromAddress);
            }

            try {
                mailOutInfo.setTargetAddresses(InternetAddress.parse(targetAddress));
            } catch (AddressException e) {
                handleException("Invalid target address/es : " + targetAddress, e);
            }
        } else if (outTransportInfo != null && outTransportInfo instanceof MailOutTransportInfo) {
            mailOutInfo = (MailOutTransportInfo) outTransportInfo;
        }

        if (mailOutInfo != null) {
            try {
                String messageID = sendMail(mailOutInfo, msgCtx);
                // this is important in axis2 client side if the mail transport uses anonymous addressing
                // the sender have to wait util the response comes.
                if (!msgCtx.getOptions().isUseSeparateListener() && !msgCtx.isServerSide()){
                    waitForReply(msgCtx, messageID);
                }
            } catch (MessagingException e) {
                handleException("Error generating mail message", e);
            } catch (IOException e) {
                handleException("Error generating mail message", e);
            }
        } else {
            handleException("Unable to determine out transport information to send message");
        }
    }

    private void waitForReply(MessageContext msgContext, String mailMessageID) throws AxisFault {
        // piggy back message constant is used to pass a piggy back
        // message context in asnych model
        if (!(msgContext.getAxisOperation() instanceof OutInAxisOperation) &&
                (msgContext.getProperty(org.apache.axis2.Constants.PIGGYBACK_MESSAGE) == null)) {
            return;
        }
        
        ConfigurationContext configContext = msgContext.getConfigurationContext();
        // if the mail message listner has not started we need to start it
        if (!configContext.getListenerManager().isListenerRunning(MailConstants.TRANSPORT_NAME)) {
            TransportInDescription mailTo =
                    configContext.getAxisConfiguration().getTransportIn(MailConstants.TRANSPORT_NAME);
            if (mailTo == null) {
                handleException("Could not find the transport receiver for " +
                    MailConstants.TRANSPORT_NAME);
            }
            configContext.getListenerManager().addListener(mailTo, false);
        }

        SynchronousCallback synchronousCallback = new SynchronousCallback(msgContext);
        Map callBackMap = (Map) msgContext.getConfigurationContext().
            getProperty(BaseConstants.CALLBACK_TABLE);
        callBackMap.put(mailMessageID, synchronousCallback);
        synchronized (synchronousCallback) {
            try {
                synchronousCallback.wait(msgContext.getOptions().getTimeOutInMilliSeconds());
            } catch (InterruptedException e) {
                handleException("Error occured while waiting ..", e);
            }
        }

        if (!synchronousCallback.isComplete()){
            // when timeout occurs remove this entry.
            callBackMap.remove(mailMessageID);
            handleException("Timeout while waiting for a response");
        }
    }

    /**
     * Populate email with a SOAP formatted message
     * @param outInfo the out transport information holder
     * @param msgContext the message context that holds the message to be written
     * @throws AxisFault on error
     * @return id of the send mail message
     */
    private String sendMail(MailOutTransportInfo outInfo, MessageContext msgContext)
        throws AxisFault, MessagingException, IOException {

        OMOutputFormat format = BaseUtils.getOMOutputFormat(msgContext);
        // Make sure that non textual attachements are sent with base64 transfer encoding
        // instead of binary.
        format.setProperty(OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS, true);
        
        MessageFormatter messageFormatter = BaseUtils.getMessageFormatter(msgContext);

        if (log.isDebugEnabled()) {
            log.debug("Creating MIME message using message formatter " +
                    messageFormatter.getClass().getSimpleName());
        }

        WSMimeMessage message = null;
        if (outInfo.getFromAddress() != null) {
            message = new WSMimeMessage(session, outInfo.getFromAddress().getAddress());
        } else {
            message = new WSMimeMessage(session, "");
        }


        Map trpHeaders = (Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
        if (log.isDebugEnabled() && trpHeaders != null) {
            log.debug("Using transport headers: " + trpHeaders);
        }

        // set From address - first check if this is a reply, then use from address from the
        // transport out, else if any custom transport headers set on this message, or default
        // to the transport senders default From address        
        if (outInfo.getTargetAddresses() != null && outInfo.getFromAddress() != null) {
            if (log.isDebugEnabled()) {
                log.debug("Setting From header to " + outInfo.getFromAddress().getAddress() +
                        " from OutTransportInfo");
            }
            message.setFrom(outInfo.getFromAddress());
            message.setReplyTo((new Address []{outInfo.getFromAddress()}));
        } else if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_FROM)) {
            InternetAddress from =
                new InternetAddress((String) trpHeaders.get(MailConstants.MAIL_HEADER_FROM));
            if (log.isDebugEnabled()) {
                log.debug("Setting From header to " + from.getAddress() +
                        " from transport headers");
            }
            message.setFrom(from);
            message.setReplyTo(new Address[] { from });
        } else {
            if (smtpFromAddress != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Setting From header to " + smtpFromAddress.getAddress() +
                            " from transport configuration");
                }
                message.setFrom(smtpFromAddress);
                message.setReplyTo(new Address[] {smtpFromAddress});
            } else {
                handleException("From address for outgoing message cannot be determined");
            }
        }

        // set To address/es to any custom transport header set on the message, else use the reply
        // address from the out transport information
        if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_TO)) {
            Address[] to =
                InternetAddress.parse((String) trpHeaders.get(MailConstants.MAIL_HEADER_TO)); 
            if (log.isDebugEnabled()) {
                log.debug("Setting To header to " + InternetAddress.toString(to) +
                        " from transport headers");
            }
            message.setRecipients(Message.RecipientType.TO, to);
        } else if (outInfo.getTargetAddresses() != null) {
            if (log.isDebugEnabled()) {
                log.debug("Setting To header to " + InternetAddress.toString(
                        outInfo.getTargetAddresses()) + " from OutTransportInfo");
            }
            message.setRecipients(Message.RecipientType.TO, outInfo.getTargetAddresses());
        } else {
            handleException("To address for outgoing message cannot be determined");
        }

        // set Cc address/es to any custom transport header set on the message, else use the
        // Cc list from original request message
        if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_CC)) {
            Address[] cc =
                InternetAddress.parse((String) trpHeaders.get(MailConstants.MAIL_HEADER_CC)); 
            if (log.isDebugEnabled()) {
                log.debug("Setting Cc header to " + InternetAddress.toString(cc) +
                        " from transport headers");
            }
            message.setRecipients(Message.RecipientType.CC, cc);
        } else if (outInfo.getCcAddresses() != null) {
            if (log.isDebugEnabled()) {
                log.debug("Setting Cc header to " + InternetAddress.toString(
                        outInfo.getCcAddresses()) + " from OutTransportInfo");
            }
            message.setRecipients(Message.RecipientType.CC, outInfo.getCcAddresses());
        }

        // set Bcc address/es to any custom addresses set at the transport sender level + any
        // custom transport header
        if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_BCC)) {
            InternetAddress[] bcc =
                InternetAddress.parse((String) trpHeaders.get(MailConstants.MAIL_HEADER_BCC));
            if (log.isDebugEnabled()) {
                log.debug("Adding Bcc header values " + InternetAddress.toString(bcc) +
                        " from transport headers");
            }
            message.addRecipients(Message.RecipientType.BCC, bcc);
        }
        if (smtpBccAddresses != null) {
            if (log.isDebugEnabled()) {
                log.debug("Adding Bcc header values " + InternetAddress.toString(smtpBccAddresses) +
                        " from transport configuration");
            }
            message.addRecipients(Message.RecipientType.BCC, smtpBccAddresses);
        }

        // set subject
        if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_SUBJECT)) {
            if (log.isDebugEnabled()) {
                log.debug("Setting Subject header to '" + trpHeaders.get(
                        MailConstants.MAIL_HEADER_SUBJECT) + "' from transport headers");
            }
            message.setSubject((String) trpHeaders.get(MailConstants.MAIL_HEADER_SUBJECT));
        } else if (outInfo.getSubject() != null) {
            if (log.isDebugEnabled()) {
                log.debug("Setting Subject header to '" + outInfo.getSubject() +
                        "' from transport headers");
            }
            message.setSubject(outInfo.getSubject());
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Generating default Subject header from SOAP action");
            }
            message.setSubject(BaseConstants.SOAPACTION + ": " + msgContext.getSoapAction());
        }

        //TODO: use a combined message id for smtp so that it generates a unique id while
        // being able to support asynchronous communication.
        // if a custom message id is set, use it
//        if (msgContext.getMessageID() != null) {
//            message.setHeader(MailConstants.MAIL_HEADER_MESSAGE_ID, msgContext.getMessageID());
//            message.setHeader(MailConstants.MAIL_HEADER_X_MESSAGE_ID, msgContext.getMessageID());
//        }

        // if this is a reply, set reference to original message
        if (outInfo.getRequestMessageID() != null) {
            message.setHeader(MailConstants.MAIL_HEADER_IN_REPLY_TO, outInfo.getRequestMessageID());
            message.setHeader(MailConstants.MAIL_HEADER_REFERENCES, outInfo.getRequestMessageID());

        } else {
            if (trpHeaders != null &&
                trpHeaders.containsKey(MailConstants.MAIL_HEADER_IN_REPLY_TO)) {
                message.setHeader(MailConstants.MAIL_HEADER_IN_REPLY_TO,
                    (String) trpHeaders.get(MailConstants.MAIL_HEADER_IN_REPLY_TO));
            }
            if (trpHeaders != null && trpHeaders.containsKey(MailConstants.MAIL_HEADER_REFERENCES)) {
                message.setHeader(MailConstants.MAIL_HEADER_REFERENCES,
                    (String) trpHeaders.get(MailConstants.MAIL_HEADER_REFERENCES));
            }
        }

        // set Date
        message.setSentDate(new Date());


        // set SOAPAction header
        message.setHeader(BaseConstants.SOAPACTION, msgContext.getSoapAction());

        // write body
        DataHandler dataHandler = new DataHandler(messageFormatter.getDataSource(msgContext, format, msgContext.getSoapAction()));
        
        MimeMultipart mimeMultiPart = null;

        String mFormat = (String) msgContext.getProperty(MailConstants.TRANSPORT_MAIL_FORMAT);
        if (mFormat == null) {
            mFormat = defaultMailFormat;
        }

        if (log.isDebugEnabled()) {
            log.debug("Using mail format '" + mFormat + "'");
        }

        MimePart mainPart;
        if (MailConstants.TRANSPORT_FORMAT_MP.equals(mFormat)) {
            mimeMultiPart = new MimeMultipart();
            MimeBodyPart mimeBodyPart1 = new MimeBodyPart();
            mimeBodyPart1.setContent("Web Service Message Attached","text/plain");
            MimeBodyPart mimeBodyPart2 = new MimeBodyPart();
            mimeMultiPart.addBodyPart(mimeBodyPart1);
            mimeMultiPart.addBodyPart(mimeBodyPart2);
            message.setContent(mimeMultiPart);
            mainPart = mimeBodyPart2;
        } else if (MailConstants.TRANSPORT_FORMAT_ATTACHMENT.equals(mFormat)) {
            mimeMultiPart = new MimeMultipart();
            MimeBodyPart mimeBodyPart1 = new MimeBodyPart();
            mimeBodyPart1.setContent("Web Service Message Attached","text/plain");
            MimeBodyPart mimeBodyPart2 = new MimeBodyPart();
            mimeMultiPart.addBodyPart(mimeBodyPart1);
            mimeMultiPart.addBodyPart(mimeBodyPart2);
            message.setContent(mimeMultiPart);

            String fileName = (String) msgContext.getProperty(
                    MailConstants.TRANSPORT_FORMAT_ATTACHMENT_FILE);
            if (fileName != null) {
                mimeBodyPart2.setFileName(fileName);
            } else {
                mimeBodyPart2.setFileName("attachment");
            }

            mainPart = mimeBodyPart2;
        } else {
            mainPart = message;
        }

        try {
            mainPart.setHeader(BaseConstants.SOAPACTION, msgContext.getSoapAction());
            mainPart.setDataHandler(dataHandler);
            
            // AXIOM's idea of what is textual also includes application/xml and
            // application/soap+xml (which JavaMail considers as binary). For these content types
            // always use quoted-printable transfer encoding. Note that JavaMail is a bit smarter
            // here because it can choose between 7bit and quoted-printable automatically, but it
            // needs to scan the entire content to determine this.
            if (msgContext.getOptions().getProperty("Content-Transfer-Encoding") != null) {
                mainPart.setHeader("Content-Transfer-Encoding",
                        (String) msgContext.getOptions().getProperty("Content-Transfer-Encoding"));
            } else {
                ContentType contentType = new ContentType(dataHandler.getContentType());
                if (!contentType.getMediaType().hasPrimaryType("multipart") && contentType.isTextual()) {
                    mainPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
                }
            }

            //setting any custom headers defined by the user
            if (msgContext.getOptions().getProperty(MailConstants.TRANSPORT_MAIL_CUSTOM_HEADERS) != null) {
                Map customTransportHeaders = (Map)msgContext.getOptions().getProperty(MailConstants.TRANSPORT_MAIL_CUSTOM_HEADERS);
                for (Object header: customTransportHeaders.keySet()){
                    mainPart.setHeader((String)header,(String)customTransportHeaders.get(header));
                }
            }


            
            log.debug("Sending message");
            Transport.send(message);

            // update metrics
            metrics.incrementMessagesSent(msgContext);
            long bytesSent = message.getBytesSent();
            if (bytesSent != -1) {
                metrics.incrementBytesSent(msgContext, bytesSent);
            }

        } catch (MessagingException | ParseException e) {
            metrics.incrementFaultsSending();
            handleException("Error creating mail message or sending it to the configured server", e);
            
        }
        return message.getMessageID();
    }

    @Override
    public void stop() {
        super.stop();
        metrics.reset();
        smtpUsername = null;
        smtpPassword = null;
        smtpBccAddresses = null;
        smtpFromAddress = null;
        session = null;
    }    
}
