package com.ozacc.mail.impl;

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import com.ozacc.mail.Mail;

/**
 * MimeMessageインスタンスを生成するクラス。
 * 
 * @author Tomohiro Otsuka
 * @version $Id: MimeMessageBuilder.java,v 1.3 2004/09/10 07:34:51 otsuka Exp $
 */
public class MimeMessageBuilder {

	private MimeMessage message;

	private String charset = Mail.JIS_CHARSET;

	private boolean hasRecipient = false;

	/**
	 * コンストラクタ。
	 * デフォルトの文字コード ISO-2022-JP がエンコーディングに使用されます。
	 * 
	 * @param mimeMessage
	 */
	public MimeMessageBuilder(MimeMessage mimeMessage) {
		this.message = mimeMessage;
	}

	/**
	 * コンストラクタ。
	 * 本文や件名のエンコーディングに使用する文字コードを指定します。
	 * 
	 * @param mimeMessage
	 * @param charset エンコーディングに使用する文字コード
	 */
	public MimeMessageBuilder(MimeMessage mimeMessage, String charset) {
		this.message = mimeMessage;
		this.charset = charset;
	}

	/**
	 * コンストラクタの引数で渡されたMimeMessageをそのまま返します。
	 * 
	 * @return MimeMessage
	 */
	public MimeMessage getMimeMessage() {
		return this.message;
	}

	/**
	 * 指定されたメールからMimeMessageを生成します。
	 * 
	 * @param mail MimeMessageのソースとなるMail
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	public void buildMimeMessage(Mail mail) throws UnsupportedEncodingException, MessagingException {

		setFrom(mail);

		setSubject(mail);

		setText(mail);

		setTo(mail);

		setCc(mail);

		setBcc(mail);

		setReplyTo(mail);

		setXHeaders(mail);

		setImportance(mail);

		if (!hasRecipient) {
			throw new MessagingException("宛先の指定がありません。To、Cc、Bccのいずれか一つは指定する必要があります。");
		}

	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setXHeaders(Mail mail) throws MessagingException {
		Map headers = mail.getXHeaders();
		if (headers == null) {
			return;
		}

		Iterator itr = headers.keySet().iterator();
		while (itr.hasNext()) {
			String key = (String)itr.next();
			String value = (String)headers.get(key);
			message.setHeader(key, value);
		}
	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setImportance(Mail mail) throws MessagingException {
		if (mail.getImportance() != null) {
			message.setHeader("Importance", mail.getImportance());

			int level = 3;
			if (Mail.Importance.HIGH.equals(mail.getImportance())) {
				level = 1;
			} else if (Mail.Importance.LOW.equals(mail.getImportance())) {
				level = 5;
			}
			message.setHeader("X-Priority", String.valueOf(level));
		}
	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setReplyTo(Mail mail) throws MessagingException {
		if (mail.getReplyTo() != null) {
			message.setReplyTo(new InternetAddress[] { mail.getReplyTo() });
		}
	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setBcc(Mail mail) throws MessagingException {
		if (mail.getBcc().length > 0) {
			message.setRecipients(MimeMessage.RecipientType.BCC, mail.getBcc());
			hasRecipient = true;
		}
	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setCc(Mail mail) throws MessagingException {
		if (mail.getCc().length > 0) {
			message.setRecipients(MimeMessage.RecipientType.CC, mail.getCc());
			hasRecipient = true;
		}
	}

	/**
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setTo(Mail mail) throws MessagingException {
		if (mail.getTo().length > 0) {
			message.setRecipients(MimeMessage.RecipientType.TO, mail.getTo());
			hasRecipient = true;
		}
	}

	/**
	 * 本文をセット。
	 * <p>
	 * NOTE: 本文の最後に改行がないとMozilla系のメーラーで最終行の日本語が文字化けしてしまう為、
	 * message.setTextの引数で最後に\nを追加している。
	 * 
	 * @param mail 
	 * @throws MessagingException
	 */
	private void setText(Mail mail) throws MessagingException {
		if (charset != null) {
			message.setText(mail.getText() + "\n", charset);
			if (charset.equalsIgnoreCase(Mail.JIS_CHARSET)) {
				message.setHeader("Content-Transfer-Encoding", "7bit");
			}
		} else {
			message.setText(mail.getText());
		}
	}

	/**
	 * @param mail
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	private void setSubject(Mail mail) throws UnsupportedEncodingException, MessagingException {
		if (charset != null) {
			if (charset.equalsIgnoreCase(Mail.JIS_CHARSET)) {
				message.setSubject(MimeUtility.encodeText(mail.getSubject(), charset, "B"));
			} else {
				message.setSubject(mail.getSubject(), charset);
			}
		} else {
			message.setSubject(mail.getSubject());
		}
	}

	/**
	 * @param mail
	 * @throws MessagingException 
	 */
	private void setFrom(Mail mail) throws MessagingException {
		message.setFrom(mail.getFrom());
	}

}