/*
 * 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.junit.Assert.*;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.mail.resolver.DataSourceClassPathResolver;
import org.apache.commons.mail.resolver.DataSourceCompositeResolver;
import org.apache.commons.mail.resolver.DataSourceUrlResolver;
import org.apache.commons.mail.mocks.MockImageHtmlEmailConcrete;
import org.apache.commons.mail.util.MimeMessageParser;
import org.apache.commons.mail.util.MimeMessageUtils;
import org.junit.Before;
import org.junit.Test;

import javax.activation.DataSource;
import javax.mail.internet.MimeMessage;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ImageHtmlEmailTest extends HtmlEmailTest {

    private static final boolean TEST_IS_LENIENT = true;
    private static final URL TEST_IMAGE_URL = ImageHtmlEmailTest.class.getResource("/images/asf_logo_wide.gif");
    private static final File TEST_IMAGE_DIR = new File(TEST_IMAGE_URL.getPath()).getParentFile();
    private static final URL TEST_HTML_URL = ImageHtmlEmailTest.class.getResource("/attachments/download_email.cgi.html");
    private static final URL TEST2_HTML_URL = ImageHtmlEmailTest.class.getResource("/attachments/classpathtest.html");

    private MockImageHtmlEmailConcrete email;

    @Before
    public void setupImageHtmlEmailTest() {
        // reusable objects to be used across multiple tests
        email = new MockImageHtmlEmailConcrete();
    }

    // ======================================================================
    // Start of Tests
    // ======================================================================

    @Test
    public void testSendHtml() throws Exception {

        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default";

        email = new MockImageHtmlEmailConcrete();
        email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);

        final String html = loadUrlContent(TEST_HTML_URL);

        // set the html message
        email.setHtmlMsg(html);

        // set the alternative message
        email.setTextMsg("Your email client does not support HTML messages");

        // send the email
        email.send();

        fakeMailServer.stop();

        assertEquals(1, fakeMailServer.getMessages().size());
        final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();

        final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
        assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
        assertTrue(mimeMessageParser.getAttachmentList().size() == 3);
    }

    @Test
    public void testSendEmptyHTML() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        final ImageHtmlEmail email = new ImageHtmlEmail();

        // set the html message
        try {
            email.setHtmlMsg(null);
            fail("Should fail here!");
        } catch (final EmailException e) {
            assertTrue(e.getMessage(), e.getMessage().contains("Invalid message supplied"));
        }
    }

    @Test
    public void testSendEmptyHTML2() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        final ImageHtmlEmail email = new ImageHtmlEmail();

        // set the html message
        try {
            email.setHtmlMsg("");
            fail("Should fail here!");
        } catch (final EmailException e) {
            assertTrue(e.getMessage(), e.getMessage().contains("Invalid message supplied"));
        }

    }

    @Test
    public void testSendHtmlUrl() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        getMailServer();

        final String strSubject = "Test HTML Send default with URL";

        // Create the email message
        email = new MockImageHtmlEmailConcrete();
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);
        email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));

        // set the html message
        email.setHtmlMsg(
                "<html><body><img src=\"http://www.apache.org/images/feather.gif\"/></body></html>"
        );

        // send the email
        email.send();

        fakeMailServer.stop();
        // validate txt message
        validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
                email.getFromAddress(), email.getToAddresses(),
                email.getCcAddresses(), email.getBccAddresses(), true);
    }

    @Test
    public void testSendHTMLAbsoluteLocalFile() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default with absolute local path";

        // Create the email message
        email = new MockImageHtmlEmailConcrete();
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);
        email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));

        final File file = File.createTempFile("emailtest", ".tst");
        FileUtils.writeStringToFile(file,
                "just some silly data that we won't be able to display anyway");

        // set the html message
        email.setHtmlMsg("<html><body><img src=\"" + file.getAbsolutePath()
                + "\"/></body></html>"
        );

        // send the email
        email.send();

        fakeMailServer.stop();
        // validate txt message
        validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
                email.getFromAddress(), email.getToAddresses(),
                email.getCcAddresses(), email.getBccAddresses(), true);
    }

    @Test
    public void testSendHTMLClassPathFile() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default";

        email = new MockImageHtmlEmailConcrete();
        email.setDataSourceResolver(new DataSourceClassPathResolver("/", TEST_IS_LENIENT));
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);

        final String html = loadUrlContent(TEST2_HTML_URL);

        // set the html message
        email.setHtmlMsg(html);

        // set the alternative message
        email.setTextMsg("Your email client does not support HTML messages");

        // send the email
        email.send();

        fakeMailServer.stop();

        assertEquals(1, fakeMailServer.getMessages().size());
        final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
        MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLClassPathFile.eml"));

        final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
        assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
        assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
    }

    @Test
    public void testSendClassPathFileWithNullName() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default";

        email = new MockImageHtmlEmailConcrete();
        email.setDataSourceResolver(new MockDataSourceClassPathResolver("/", TEST_IS_LENIENT));
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);

        final String html = loadUrlContent(TEST2_HTML_URL);

        // set the html message
        email.setHtmlMsg(html);

        // set the alternative message
        email.setTextMsg("Your email client does not support HTML messages");

        // send the email
        email.send();

        fakeMailServer.stop();

        assertEquals(1, fakeMailServer.getMessages().size());
        final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
        MimeMessageUtils.writeMimeMessage(mimeMessage,
                new File("./target/test-emails/testSendClassPathFileWithNullName.eml"));

        final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
        assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
        assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
    }

    @Test
    public void testSendHTMLAutoResolveFile() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default";

        email = new MockImageHtmlEmailConcrete();
        final DataSourceResolver dataSourceResolvers[] = new DataSourceResolver[2];
        dataSourceResolvers[0] = new DataSourceUrlResolver(new URL("http://foo"), true);
        dataSourceResolvers[1] = new DataSourceClassPathResolver("/", true);

        email.setDataSourceResolver(new DataSourceCompositeResolver(dataSourceResolvers));
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);

        final String html = loadUrlContent(TEST2_HTML_URL);

        // set the html message
        email.setHtmlMsg(html);

        // set the alternative message
        email.setTextMsg("Your email client does not support HTML messages");

        // send the email
        email.send();

        fakeMailServer.stop();

        assertEquals(1, fakeMailServer.getMessages().size());
        final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
        MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLAutoFile.eml"));

        final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
        assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
        assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
    }

    @Test
    public void testSendHTMLAutoResolveMultipleFiles() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        // Create the email message
        getMailServer();

        final String strSubject = "Test HTML Send default";

        email = new MockImageHtmlEmailConcrete();
        final DataSourceResolver dataSourceResolver = new DataSourceClassPathResolver("/", true);

        email.setDataSourceResolver(dataSourceResolver);
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);

        final String html = "<p>First image  <img src=\"images/contentTypeTest.gif\"/></p>" +
                      "<p>Second image <img src=\"images/contentTypeTest.jpg\"/></p>" +
                      "<p>Third image  <img src=\"images/contentTypeTest.png\"/></p>";

        // set the html message
        email.setHtmlMsg(html);

        // set the alternative message
        email.setTextMsg("Your email client does not support HTML messages");

        // send the email
        email.send();

        fakeMailServer.stop();

        assertEquals(1, fakeMailServer.getMessages().size());
        final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
        MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLAutoMultipleFiles.eml"));

        final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
        assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
        assertTrue(mimeMessageParser.getAttachmentList().size() == 3);
    }

    @Test
    public void testRegex() {
        final Pattern pattern = Pattern.compile(ImageHtmlEmail.REGEX_IMG_SRC);

        // ensure that the regex that we use is catching the cases correctly
        Matcher matcher = pattern
                .matcher("<html><body><img src=\"h\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("h", matcher.group(2));

        matcher = pattern
                .matcher("<html><body><img id=\"laskdasdkj\" src=\"h\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("h", matcher.group(2));

        // uppercase
        matcher = pattern
                .matcher("<html><body><IMG id=\"laskdasdkj\" SRC=\"h\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("h", matcher.group(2));

        // matches twice
        matcher = pattern
                .matcher("<html><body><img id=\"laskdasdkj\" src=\"http://dstadler1.org/\"/><img id=\"laskdasdkj\" src=\"http://dstadler2.org/\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("http://dstadler1.org/", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("http://dstadler2.org/", matcher.group(2));

        // what about newlines
        matcher = pattern
                .matcher("<html><body><img\n \rid=\"laskdasdkj\"\n \rsrc=\"http://dstadler1.org/\"/><img id=\"laskdasdkj\" src=\"http://dstadler2.org/\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("http://dstadler1.org/", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("http://dstadler2.org/", matcher.group(2));

        // what about newlines and other whitespaces
        matcher = pattern
                .matcher("<html><body><img\n \t\rid=\"laskdasdkj\"\n \rsrc \n =\r  \"http://dstadler1.org/\"/><img  \r  id=\" laskdasdkj\"    src    =   \"http://dstadler2.org/\"/></body></html>");
        assertTrue(matcher.find());
        assertEquals("http://dstadler1.org/", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("http://dstadler2.org/", matcher.group(2));

        // what about some real markup
        matcher = pattern.matcher("<img alt=\"Chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0\" src=\"/chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0.2&amp;l=A,C,S,T&amp;v=3.0,3.0,2.0,2.0\"");
        assertTrue(matcher.find());
        assertEquals("/chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0.2&amp;l=A,C,S,T&amp;v=3.0,3.0,2.0,2.0", matcher.group(2));

        // had a problem with multiple img-source tags
        matcher = pattern
                .matcher("<img src=\"file1\"/><img src=\"file2\"/>");
        assertTrue(matcher.find());
        assertEquals("file1", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file2", matcher.group(2));

        matcher = pattern
                .matcher("<img src=\"file1\"/><img src=\"file2\"/><img src=\"file3\"/><img src=\"file4\"/><img src=\"file5\"/>");
        assertTrue(matcher.find());
        assertEquals("file1", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file2", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file3", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file4", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file5", matcher.group(2));

        // try with invalid HTML that is seems sometimes, i.e. without closing "/" or "</img>"
        matcher = pattern.matcher("<img src=\"file1\"><img src=\"file2\">");
        assertTrue(matcher.find());
        assertEquals("file1", matcher.group(2));
        assertTrue(matcher.find());
        assertEquals("file2", matcher.group(2));
    }

    @Test
    public void testEmail127() throws Exception {
        Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);

        getMailServer();

        final String strSubject = "Test HTML Send default with URL";

        // Create the email message
        email = new MockImageHtmlEmailConcrete();
        email.setHostName(strTestMailServer);
        email.setSmtpPort(getMailServerPort());
        email.setFrom(strTestMailFrom);
        email.addTo(strTestMailTo);
        email.setSubject(strSubject);
        email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));

        // set the html message
        email.setHtmlMsg("<html><body><img title=\"$\" src=\"http://www.apache.org/images/feather.gif\"/></body></html>");

        // send the email
        email.send();

        fakeMailServer.stop();
        // validate txt message
        validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
                     email.getFromAddress(), email.getToAddresses(),
                     email.getCcAddresses(), email.getBccAddresses(), true);
    }

    private String loadUrlContent(final URL url) throws IOException {
        final InputStream stream = url.openStream();
        final StringBuilder html = new StringBuilder();
        try {
            final List<String> lines = IOUtils.readLines(stream);
            for (final String line : lines) {
                html.append(line).append("\n");
            }
        } finally {
            stream.close();
        }
        return html.toString();
    }

    private static final class MockDataSourceClassPathResolver extends DataSourceClassPathResolver {

        public MockDataSourceClassPathResolver(final String classPathBase, final boolean lenient) {
            super(classPathBase, lenient);
        }

        @Override
        public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
            final javax.mail.util.ByteArrayDataSource ds =
                    (javax.mail.util.ByteArrayDataSource) super.resolve(resourceLocation, isLenient);
            ds.setName(null);
            return ds;
        }

    }
}
