package com.ozacc.mail.impl;

import java.io.File;

import javax.mail.internet.InternetAddress;

import junit.framework.TestCase;

import org.apache.log4j.BasicConfigurator;
import org.apache.velocity.VelocityContext;

import com.ozacc.mail.Mail;
import com.ozacc.mail.MailBuildException;

/**
 * XMLMailBuilderのテストケース。
 * 
 * @author Tomohiro Otsuka
 * @version $Id: JDomXMLMailBuilderTest.java,v 1.3.2.2 2005/02/01 20:38:14 otsuka Exp $
 */
public class JDomXMLMailBuilderTest extends TestCase {

	private JDomXMLMailBuilder builder;

	protected void setUp() throws Exception {
		super.setUp();
		BasicConfigurator.configure();

		builder = new JDomXMLMailBuilder();
	}

	protected void tearDown() throws Exception {
		super.tearDown();
		BasicConfigurator.resetConfiguration();
	}

	public final void testBuildMailCDATA() throws Exception {
		String classPath = "/com/ozacc/mail/test-mail6-cdata.xml";

		String expectedBody = "これはCDATAのテキストです。";

		Mail result = builder.buildMail(classPath);

		assertEquals(expectedBody, result.getText());
	}

	/*
	 * Class under test for Mail buildMail(String)
	 * 存在しないファイルのパスを指定して失敗。
	 */
	public final void testBuildMailFromClassPathNotExist() throws Exception {
		String classPath = "/com/ozacc/mail/testtest-mail1.xml";
		try {
			Mail result = builder.buildMail(classPath);
			fail("This should never be called.");
		} catch (MailBuildException expected) {
			// success
		}
	}

	/*
	 * Class under test for Mail buildMail(File)
	 * 存在しないファイルを指定して失敗
	 */
	public final void testBuildMailFromFileNotExist() throws Exception {
		String path = "src/test/com/ozacc/mail/testtest-mail1.xml";
		File file = new File(path);
		try {
			Mail result = builder.buildMail(file);
			fail("This should never be called.");
		} catch (MailBuildException expected) {
			// success
		}
	}

	/*
	 * Class under test for Mail buildMail(String)
	 * DTD違反のXMLのため失敗。
	 */
	public final void testBuildMailFromClassPathInvalidXML() throws Exception {
		String classPath = "/com/ozacc/mail/test-mail2-invalid.xml";
		try {
			Mail result = builder.buildMail(classPath);
			fail("This should never be called.");
		} catch (MailBuildException expected) {
			// success
		}
	}

	/*
	 * Class under test for Mail buildMail(String)
	 * XMLファイルのクラスパスからMailインスタンスを生成。
	 */
	public final void testBuildMailFromClassPath() throws Exception {
		String classPath = "/com/ozacc/mail/test-mail1.xml";

		String subject = "XMLMailBuilderのテストケース";
		String text = "改行します。\n改行しました。\nテストは成功。";

		InternetAddress from = new InternetAddress("from@example.com", "差出人");
		InternetAddress returnPath = new InternetAddress("return@example.com");
		InternetAddress replyTo = new InternetAddress("reply@example.com");

		InternetAddress to1 = new InternetAddress("to1@example.com", "宛先1");
		InternetAddress to2 = new InternetAddress("to2@example.com");

		InternetAddress cc1 = new InternetAddress("cc1@example.com", "CC1");
		InternetAddress cc2 = new InternetAddress("cc2@example.com");

		InternetAddress bcc = new InternetAddress("bcc@example.com");

		Mail result = builder.buildMail(classPath);

		assertEquals(subject, result.getSubject());
		assertEquals(text, result.getText());

		assertEquals(from, result.getFrom());
		assertEquals(returnPath, result.getReturnPath());
		assertEquals(replyTo, result.getReplyTo());

		InternetAddress[] tos = result.getTo();
		assertEquals(2, tos.length);
		assertEquals(to1, tos[0]);
		assertEquals(to2, tos[1]);

		InternetAddress[] ccs = result.getCc();
		assertEquals(2, ccs.length);
		assertEquals(cc1, ccs[0]);
		assertEquals(cc2, ccs[1]);

		InternetAddress[] bccs = result.getBcc();
		assertEquals(1, bccs.length);
		assertEquals(bcc, bccs[0]);
	}

	/*
	 * Class under test for Mail buildMail(File)
	 * XMLファイルのFileインスタンスからMailインスタンスを生成。
	 */
	public final void testBuildMailFromFile() throws Exception {
		String path = "src/test/com/ozacc/mail/test-mail1.xml";
		File file = new File(path);

		String subject = "XMLMailBuilderのテストケース";
		String text = "改行します。\n改行しました。\nテストは成功。";

		InternetAddress from = new InternetAddress("from@example.com", "差出人");
		InternetAddress returnPath = new InternetAddress("return@example.com");
		InternetAddress replyTo = new InternetAddress("reply@example.com");

		InternetAddress to1 = new InternetAddress("to1@example.com", "宛先1");
		InternetAddress to2 = new InternetAddress("to2@example.com");

		InternetAddress cc1 = new InternetAddress("cc1@example.com", "CC1");
		InternetAddress cc2 = new InternetAddress("cc2@example.com");

		InternetAddress bcc = new InternetAddress("bcc@example.com");

		Mail result = builder.buildMail(file);

		assertEquals(subject, result.getSubject());
		assertEquals(text, result.getText());

		assertEquals(from, result.getFrom());
		assertEquals(returnPath, result.getReturnPath());
		assertEquals(replyTo, result.getReplyTo());

		InternetAddress[] tos = result.getTo();
		assertEquals(2, tos.length);
		assertEquals(to1, tos[0]);
		assertEquals(to2, tos[1]);

		InternetAddress[] ccs = result.getCc();
		assertEquals(2, ccs.length);
		assertEquals(cc1, ccs[0]);
		assertEquals(cc2, ccs[1]);

		InternetAddress[] bccs = result.getBcc();
		assertEquals(1, bccs.length);
		assertEquals(bcc, bccs[0]);
	}

	/*
	 * Class under test for Mail buildMail(String, VelocityContext)
	 */
	public final void testBuildMailStringVelocityContext() throws Exception {
		String classPath = "/com/ozacc/mail/test-mail3-velocity.xml";

		String name = "伊東美咲";
		String email = "misaki@example.com";
		Customer customer = new Customer(name, email);
		String item = "GIVE&TAKE (Beige)\n\nDesigned by：Ronan & Erwan Boroullec, Size：W313*D84*H370, Color：グリーン, 本体：ABS樹脂";

		InternetAddress from = new InternetAddress("shop@example.com", "XMLMailBuilderオンラインショップ");
		InternetAddress to = new InternetAddress(email, name);

		String subject = "XMLMailBuilderオンラインショップ - ご注文の確認";
		String text = name
				+ "様\n\nお買い上げありがとうございました。\n\nGIVE&TAKE (Beige)\n\nDesigned by：Ronan & Erwan Boroullec, Size：W313*D84*H370, Color：グリーン, 本体：ABS樹脂";

		VelocityContext context = new VelocityContext();
		context.put("customer", customer);
		context.put("item", item);

		// メール生成実行
		Mail result = builder.buildMail(classPath, context);

		assertEquals(from, result.getFrom());
		assertEquals(to, result.getTo()[0]);
		assertEquals(subject, result.getSubject());
		assertEquals(text, result.getText());
	}

	/*
	 * Class under test for Mail buildMail(File, VelocityContext)
	 */
	public final void testBuildMailFileVelocityContext() throws Exception {
		String path = "src/test/com/ozacc/mail/test-mail3-velocity.xml";
		File file = new File(path);

		String name = "伊東美咲";
		String email = "misaki@example.com";
		Customer customer = new Customer(name, email);
		String item = "GIVE&TAKE (Beige)\n\nDesigned by：Ronan & Erwan Boroullec, Size：W313*D84*H370, Color：グリーン, 本体：ABS樹脂";

		InternetAddress from = new InternetAddress("shop@example.com", "XMLMailBuilderオンラインショップ");
		InternetAddress to = new InternetAddress(email, name);

		String subject = "XMLMailBuilderオンラインショップ - ご注文の確認";
		String text = name
				+ "様\n\nお買い上げありがとうございました。\n\nGIVE&TAKE (Beige)\n\nDesigned by：Ronan & Erwan Boroullec, Size：W313*D84*H370, Color：グリーン, 本体：ABS樹脂";

		VelocityContext context = new VelocityContext();
		context.put("customer", customer);
		context.put("item", item);

		// メール生成実行
		Mail result = builder.buildMail(file, context);

		assertEquals(from, result.getFrom());
		assertEquals(to, result.getTo()[0]);
		assertEquals(subject, result.getSubject());
		assertEquals(text, result.getText());
	}

	public void testBuildMailFromMultipleMailsTemplate() throws Exception {
		String path = "src/test/com/ozacc/mail/test-mail7-multiple.xml";
		File file = new File(path);

		Mail result1 = builder.buildMail(file, "first");
		assertEquals("1通目", result1.getText());

		Mail result2 = builder.buildMail(file, "second");
		assertEquals("2通目", result2.getText());

		try {
			Mail result3 = builder.buildMail(file, "サード");
		} catch (MailBuildException expected) {

		}
	}

	public static class Customer {

		private String name;

		private String email;

		public Customer(String name, String email) {
			this.name = name;
			this.email = email;
		}

		/**
		 * @return Returns the email.
		 */
		public String getEmail() {
			return email;
		}

		/**
		 * @param email The email to set.
		 */
		public void setEmail(String email) {
			this.email = email;
		}

		/**
		 * @return Returns the name.
		 */
		public String getName() {
			return name;
		}

		/**
		 * @param name The name to set.
		 */
		public void setName(String name) {
			this.name = name;
		}
	}

}