/*
 * 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 static org.easymock.EasyMock.expect;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.*;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.replay;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.BindException;
import java.net.URL;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

import javax.activation.DataHandler;
import javax.mail.Header;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.mail.settings.EmailConfiguration;
import org.junit.After;
import org.junit.Before;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;

/**
 * Base test case for Email test classes.
 *
 * @since 1.0
 */
public abstract class AbstractEmailTest
{
    /** Padding at end of body added by wiser/send */
    public static final int BODY_END_PAD = 3;

    /** Padding at start of body added by wiser/send */
    public static final int BODY_START_PAD = 2;

    /** Line separator in email messages */
    private static final String LINE_SEPARATOR = "\r\n";

    /** default port */
    private static int mailServerPort = 2500;

    /** The fake Wiser email server */
    protected Wiser fakeMailServer;

    /** Mail server used for testing */
    protected String strTestMailServer = "localhost";

    /** From address for the test email */
    protected String strTestMailFrom = "test_from@apache.org";

    /** Destination address for the test email */
    protected String strTestMailTo = "test_to@apache.org";

    /** Mailserver username (set if needed) */
    protected String strTestUser = "user";

    /** Mailserver strTestPasswd (set if needed) */
    protected String strTestPasswd = "password";

    /** URL to used to test URL attachments (Must be valid) */
    protected String strTestURL = EmailConfiguration.TEST_URL;

    /** Test characters acceptable to email */
    protected String[] testCharsValid =
    {
            " ",
            "a",
            "A",
            "\uc5ec",
            "0123456789",
            "012345678901234567890"
    };

    /** Test characters not acceptable to email */
    protected String[] endOfLineCombinations =
    {
            "\n",
            "\r",
            "\r\n",
            "\n\r",
    };

    /** Array of test strings */
    protected String[] testCharsNotValid = {"", null};

    /** Where to save email output **/
    private File emailOutputDir;

    /** counter for creating a file name */
    private static int fileNameCounter;

    @Before
    public void setUpAbstractEmailTest()
    {
        emailOutputDir = new File("target/test-emails");
        if (!emailOutputDir.exists())
        {
            emailOutputDir.mkdirs();
        }
    }

    @After
    public void tearDownEmailTest()
    {
        //stop the fake email server (if started)
        if (this.fakeMailServer != null && !isMailServerStopped(fakeMailServer))
        {
            this.fakeMailServer.stop();
            assertTrue("Mail server didn't stop", isMailServerStopped(fakeMailServer));
        }

        this.fakeMailServer = null;
    }

    /**
     * Gets the mail server port.
     * @return the port the server is running on.
     */
    protected int getMailServerPort()
    {
        return mailServerPort;
    }

    /**
     * Safe a mail to a file using a more or less unique file name.
     *
     * @param email email
     * @throws IOException writing the email failed
     * @throws MessagingException writing the email failed
     */
    protected void saveEmailToFile(final WiserMessage email) throws IOException, MessagingException
    {
        final int currCounter = fileNameCounter++ % 10;
        final String emailFileName = "email" + new Date().getTime() + "-" + currCounter + ".eml";
        final File emailFile = new File(emailOutputDir, emailFileName);
        EmailUtils.writeMimeMessage(emailFile, email.getMimeMessage() );
    }

    /**
     * @param intMsgNo the message to retrieve
     * @return message as string
     */
    public String getMessageAsString(final int intMsgNo)
    {
        final List<?> receivedMessages = fakeMailServer.getMessages();
        assertTrue("mail server didn't get enough messages", receivedMessages.size() >= intMsgNo);

        final WiserMessage emailMessage = (WiserMessage) receivedMessages.get(intMsgNo);

        if (emailMessage != null)
        {
            try
            {
                return serializeEmailMessage(emailMessage);
            }
            catch (final Exception e)
            {
                // ignore, since the test will fail on an empty string return
            }
        }
        fail("Message not found");
        return "";
    }

    /**
     * Initializes the stub mail server. Fails if the server cannot be proven
     * to have started. If the server is already started, this method returns
     * without changing the state of the server.
     */
    public void getMailServer()
    {
        if (this.fakeMailServer == null || isMailServerStopped(fakeMailServer))
        {
            mailServerPort++;

            this.fakeMailServer = new Wiser();
            this.fakeMailServer.setPort(getMailServerPort());
            try {
            	this.fakeMailServer.start();
            } catch (RuntimeException e) {
            	if (e.getCause() != null  &&  e.getCause() instanceof BindException) {
            		throw new IllegalStateException("Port " + getMailServerPort()
            		                                + " is already in use.");
            	}
            }

            assertFalse("fake mail server didn't start", isMailServerStopped(fakeMailServer));

            final Date dtStartWait = new Date();
            while (isMailServerStopped(fakeMailServer))
            {
                // test for connected
                if (this.fakeMailServer != null
                    && !isMailServerStopped(fakeMailServer))
                {
                    break;
                }

                // test for timeout
                if (dtStartWait.getTime() + EmailConfiguration.TIME_OUT
                    <= new Date().getTime())
                {
                    fail("Mail server failed to start");
                }
            }
        }
    }

    /**
     * Validate the message was sent properly
     * @param mailServer reference to the fake mail server
     * @param strSubject expected subject
     * @param fromAdd expected from address
     * @param toAdd list of expected to addresses
     * @param ccAdd list of expected cc addresses
     * @param bccAdd list of expected bcc addresses
     * @param boolSaveToFile true will output to file, false doesnt
     * @return WiserMessage email to check
     * @throws IOException Exception
     */
    protected WiserMessage validateSend(
        final Wiser mailServer,
        final String strSubject,
        final InternetAddress fromAdd,
        final List<InternetAddress> toAdd,
        final List<InternetAddress> ccAdd,
        final List<InternetAddress> bccAdd,
        final boolean boolSaveToFile)
        throws IOException
    {
        assertTrue("mail server doesn't contain expected message",
                mailServer.getMessages().size() == 1);
        final WiserMessage emailMessage = mailServer.getMessages().get(0);

        if (boolSaveToFile)
        {
            try
            {
                this.saveEmailToFile(emailMessage);
            }
            catch(final MessagingException me)
            {
                final IllegalStateException ise =
                    new IllegalStateException("caught MessagingException during saving the email");
                ise.initCause(me);
                throw ise;
            }
        }

        try
        {
            // get the MimeMessage
            final MimeMessage mimeMessage = emailMessage.getMimeMessage();

            // test subject
            assertEquals("got wrong subject from mail",
                    strSubject, mimeMessage.getHeader("Subject", null));

            //test from address
            assertEquals("got wrong From: address from mail",
                    fromAdd.toString(), mimeMessage.getHeader("From", null));

            //test to address
            assertTrue("got wrong To: address from mail",
                    toAdd.toString().contains(mimeMessage.getHeader("To", null)));

            //test cc address
            if (!ccAdd.isEmpty())
            {
                assertTrue("got wrong Cc: address from mail",
                    ccAdd.toString().contains(mimeMessage.getHeader("Cc", null)));
            }

            //test bcc address
            if (!bccAdd.isEmpty())
            {
                assertTrue("got wrong Bcc: address from mail",
                    bccAdd.toString().contains(mimeMessage.getHeader("Bcc", null)));
            }
        }
        catch (final MessagingException me)
        {
            final IllegalStateException ise =
                new IllegalStateException("caught MessagingException in validateSend()");
            ise.initCause(me);
            throw ise;
        }

        return emailMessage;
    }

    /**
     * Validate the message was sent properly
     * @param mailServer reference to the fake mail server
     * @param strSubject expected subject
     * @param content the expected message content
     * @param fromAdd expected from address
     * @param toAdd list of expected to addresses
     * @param ccAdd list of expected cc addresses
     * @param bccAdd list of expected bcc addresses
     * @param boolSaveToFile true will output to file, false doesnt
     * @throws IOException Exception
     */
    protected void validateSend(
        final Wiser mailServer,
        final String strSubject,
        final Multipart content,
        final InternetAddress fromAdd,
        final List<InternetAddress> toAdd,
        final List<InternetAddress> ccAdd,
        final List<InternetAddress> bccAdd,
        final boolean boolSaveToFile)
        throws IOException
    {
        // test other properties
        final WiserMessage emailMessage = this.validateSend(
            mailServer,
            strSubject,
            fromAdd,
            toAdd,
            ccAdd,
            bccAdd,
            boolSaveToFile);

        // test message content

        // get sent email content
        final String strSentContent =
            content.getContentType();
        // get received email content (chop off the auto-added \n
        // and -- (front and end)
        final String emailMessageBody = getMessageBody(emailMessage);
        final String strMessageBody =
            emailMessageBody.substring(AbstractEmailTest.BODY_START_PAD,
                                       emailMessageBody.length()
                                       - AbstractEmailTest.BODY_END_PAD);
        assertTrue("didn't find expected content type in message body",
                strMessageBody.contains(strSentContent));
    }

    /**
     * Validate the message was sent properly
     * @param mailServer reference to the fake mail server
     * @param strSubject expected subject
     * @param strMessage the expected message as a string
     * @param fromAdd expected from address
     * @param toAdd list of expected to addresses
     * @param ccAdd list of expected cc addresses
     * @param bccAdd list of expected bcc addresses
     * @param boolSaveToFile true will output to file, false doesnt
     * @throws IOException Exception
     */
    protected void validateSend(
        final Wiser mailServer,
        final String strSubject,
        final String strMessage,
        final InternetAddress fromAdd,
        final List<InternetAddress> toAdd,
        final List<InternetAddress> ccAdd,
        final List<InternetAddress> bccAdd,
        final boolean boolSaveToFile)
        throws IOException
    {
        // test other properties
        final WiserMessage emailMessage = this.validateSend(
            mailServer,
            strSubject,
            fromAdd,
            toAdd,
            ccAdd,
            bccAdd,
            true);

        // test message content
        assertThat("didn't find expected message content in message body",
                getMessageBody(emailMessage), containsString(strMessage));
    }

    /**
     * Serializes the {@link MimeMessage} from the {@code WiserMessage}
     * passed in. The headers are serialized first followed by the message
     * body.
     *
     * @param wiserMessage The {@code WiserMessage} to serialize.
     * @return The string format of the message.
     * @throws MessagingException
     * @throws IOException
     *             Thrown while serializing the body from
     *             {@link DataHandler#writeTo(java.io.OutputStream)}.
     * @throws MessagingException
     *             Thrown while getting the body content from
     *             {@link MimeMessage#getDataHandler()}
     * @since 1.1
     */
    private String serializeEmailMessage(final WiserMessage wiserMessage)
            throws MessagingException, IOException
    {
        if (wiserMessage == null)
        {
            return "";
        }

        final StringBuffer serializedEmail = new StringBuffer();
        final MimeMessage message = wiserMessage.getMimeMessage();

        // Serialize the headers
        for (final Enumeration<?> headers = message.getAllHeaders(); headers
                .hasMoreElements();)
        {
            final Header header = (Header) headers.nextElement();
            serializedEmail.append(header.getName());
            serializedEmail.append(": ");
            serializedEmail.append(header.getValue());
            serializedEmail.append(LINE_SEPARATOR);
        }

        // Serialize the body
        final byte[] messageBody = getMessageBodyBytes(message);

        serializedEmail.append(LINE_SEPARATOR);
        serializedEmail.append(messageBody);
        serializedEmail.append(LINE_SEPARATOR);

        return serializedEmail.toString();
    }

    /**
     * Returns a string representation of the message body. If the message body
     * cannot be read, an empty string is returned.
     *
     * @param wiserMessage The wiser message from which to extract the message body
     * @return The string representation of the message body
     * @throws IOException
     *             Thrown while serializing the body from
     *             {@link DataHandler#writeTo(java.io.OutputStream)}.
     * @since 1.1
     */
    private String getMessageBody(final WiserMessage wiserMessage)
            throws IOException
    {
        if (wiserMessage == null)
        {
            return "";
        }

        byte[] messageBody = null;

        try
        {
            final MimeMessage message = wiserMessage.getMimeMessage();
            messageBody = getMessageBodyBytes(message);
        }
        catch (final MessagingException me)
        {
            // Thrown while getting the body content from
            // {@link MimeMessage#getDataHandler()}
            final IllegalStateException ise =
                new IllegalStateException("couldn't process MimeMessage from WiserMessage in getMessageBody()");
            ise.initCause(me);
            throw ise;
        }

        return messageBody != null ? new String(messageBody).intern() : "";
    }

    /**
     * Gets the byte making up the body of the message.
     *
     * @param mimeMessage
     *            The mime message from which to extract the body.
     * @return A byte array representing the message body
     * @throws IOException
     *             Thrown while serializing the body from
     *             {@link DataHandler#writeTo(java.io.OutputStream)}.
     * @throws MessagingException
     *             Thrown while getting the body content from
     *             {@link MimeMessage#getDataHandler()}
     * @since 1.1
     */
    private byte[] getMessageBodyBytes(final MimeMessage mimeMessage)
            throws IOException, MessagingException
    {
        final DataHandler dataHandler = mimeMessage.getDataHandler();
        final ByteArrayOutputStream byteArrayOutStream = new ByteArrayOutputStream();
        final BufferedOutputStream buffOs = new BufferedOutputStream(
                byteArrayOutStream);
        dataHandler.writeTo(buffOs);
        buffOs.flush();

        return byteArrayOutStream.toByteArray();
    }

    /**
     * Checks if an email server is running at the address stored in the
     * {@code fakeMailServer}.
     *
     * @param fakeMailServer
     *            The server from which the address is picked up.
     * @return {@code true} if the server claims to be running
     * @since 1.1
     */
    protected boolean isMailServerStopped(final Wiser fakeMailServer) {
        return !fakeMailServer.getServer().isRunning();
    }

    /**
     * Create a mocked URL object which always throws an IOException
     * when the openStream() method is called.
     * <p>
     * Several ISPs do resolve invalid URLs like {@code http://example.invalid}
     * to some error page causing tests to fail otherwise.
     *
     * @return an invalid URL
     */
    protected URL createInvalidURL() throws Exception {
        final URL url = createMock(URL.class);
        expect(url.openStream()).andThrow(new IOException());
        replay(url);

        return url;
    }
}
