package com.cloudcross.ssp.base.service.impl;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import com.cloudcross.ssp.base.service.IMailService;
import com.cloudcross.ssp.base.utils.concurrent.async.AsyncToken;
import com.cloudcross.ssp.base.utils.concurrent.async.IResponder;
import com.cloudcross.ssp.base.utils.freemarker.FreemarkerTemplateProcessor;
import com.cloudcross.ssp.base.utils.mail.AsyncJavaMailSender;
import com.cloudcross.ssp.base.utils.mail.SimpleMailMessageUtils;
import com.cloudcross.ssp.base.utils.springbean.Properties;
import com.cloudcross.ssp.common.error.AppException;
import com.cloudcross.ssp.common.utils.Assert;
import com.cloudcross.ssp.common.utils.LangUtil;

/**
 * mailer服务类。 现本mailer与freemarker模板结合,用于生成邮件内容
 * 
 * <pre>
 * Mail使用规范:
 * 1. 组合mail服务类如下代码所示：
 *    <code>
 * 	   ＠Autowired
 *     private IMailService mailService;
 * 	  </code>
 * 2. 调用发送邮件方法
 *    mailService.sendMessage(...) 或者 mailService.sendMessage.sendMessageAsHTML(...)
 * </pre>
 * 
 * @author badqiu qaohao
 */
@Component
public class MailService implements InitializingBean, IMailService {
	@Autowired
	private AsyncJavaMailSender asyncJavaMailSender;
	@Autowired
	private SimpleMailMessage simpleMailMessageTemplate;
	@Autowired
	private FreemarkerTemplateProcessor freemarkerTemplateProcessor;
	// 注意：当HTML邮件时，发件人姓名才能有效。
	@Properties(name = "mail.from.name")
	private String fromName;
	@Properties(name = "mail.template.folder")
	private String mailTemplateFolder;

	/**
	 * {@author qaohao
	 */
	@Override
	public <T> AsyncToken sendMessage(String subject, String mailTemplatePath,
			Object data, String to) throws AppException {
		Assert.state(!LangUtil.isBlank(subject),
				"email 'subject' shoud not be null or empty.");
		Assert.state(!LangUtil.isBlank(mailTemplatePath),
				"email template file path 'mailTemplatePath' shoud not be null or empty.");
		Assert.notNull(data, "email template 'data' shoud not be null.");
		Assert.state(!LangUtil.isBlank(to),
				"email 'to' address shoud not be null or empty.");
		return createAndSendMessage(subject, mailTemplatePath, data, to, false);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T> AsyncToken sendMessage(String subject, String mailTemplatePath,
			Object data, String to, IResponder<T> responder)
			throws AppException {
		Assert.notNull(responder, "responder should not be null.");
		AsyncToken token = sendMessage(subject, mailTemplatePath, data, to);
		token.addResponder(responder);
		return token;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public AsyncToken sendMessageAsHTML(String subject,
			String mailTemplatePath, Object data, String to)
			throws AppException {
		Assert.state(!LangUtil.isBlank(subject),
				"email 'subject' shoud not be null or empty.");
		Assert.state(!LangUtil.isBlank(mailTemplatePath),
				"email template file path 'mailTemplatePath' shoud not be null or empty.");
		Assert.notNull(data, "email template 'data' shoud not be null.");
		Assert.state(!LangUtil.isBlank(to),
				"email 'to' address shoud not be null or empty.");
		return createAndSendMessage(subject, mailTemplatePath, data, to, true);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T> AsyncToken sendMessageAsHTML(String subject,
			String mailTemplatePath, Object data, String to,
			IResponder<T> responder) throws AppException {
		Assert.notNull(responder, "responder should not be null.");
		AsyncToken token = sendMessageAsHTML(subject, mailTemplatePath, data,
				to);
		token.addResponder(responder);
		return token;
	}

	/**
	 * 使用freemarker模板创建邮件消息
	 */
	AsyncToken createAndSendMessage(String subject, String mailTemplatePath,
			Object data, String to, boolean isHTML) {
		SimpleMailMessage msg = new SimpleMailMessage();
		if (simpleMailMessageTemplate != null) {
			simpleMailMessageTemplate.copyTo(msg);
		}

		msg.setSubject(subject);
		msg.setTo(to);
		msg.setText(processTemplate(mailTemplatePath, data));
		if (isHTML) {
			return asyncJavaMailSender.send(SimpleMailMessageUtils.toHtmlMsg(
					msg, LangUtil.replaceNull(fromName, null)));
		} else {
			return asyncJavaMailSender.send(msg);
		}
	}

	/**
	 * {@author qaohao
	 */
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(asyncJavaMailSender,
				"asyncJavaMailSender must be not null");
		Assert.notNull(freemarkerTemplateProcessor,
				"freemarkerTemplateProcessor must be not null");
	}

	public String getFromName() {
		return fromName;
	}

	public AsyncJavaMailSender getAsyncJavaMailSender() {
		return asyncJavaMailSender;
	}

	public JavaMailSender getJavaMailSender() {
		return getAsyncJavaMailSender().getJavaMailSender();
	}

	public String processTemplate(String templateName, Object model) {
		if (LangUtil.isBlank(mailTemplateFolder)) {
			return freemarkerTemplateProcessor.processTemplate(templateName,
					model);
		} else {
			return freemarkerTemplateProcessor.processTemplate(
					mailTemplateFolder.concat("/").concat(templateName), model);
		}
	}

}
