package de.dml.application.mail;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Component;
import org.springframework.ui.velocity.VelocityEngineUtils;

import de.dml.application.kernel.ApplicationKernel;
import de.dml.application.mail.configSettings.MailFromAddress;
import de.dml.application.mail.configSettings.MailFromAlias;
import de.dml.application.mail.configSettings.MailReplyAddress;
import de.dml.application.persistence.core.entityDao.CoreConfigDao;

/**
 * This class represents a default email message preparator, that takes care about templated layouting etc. This class
 * should be used whenever the application is required to send email notifications.
 * 
 * @author ssmits
 */
@Component
public class EmailMessagePreparator implements MimeMessagePreparator, Serializable {
	private static final long serialVersionUID = 1L;

	@Autowired private VelocityEngine velocityEngine;
	@Autowired private CoreConfigDao coreConfigDao;
	@Autowired private ApplicationKernel applicationKernel;
	
	private String messageLayoutTemplate = "templates/email/messageLayout/template.html";
	
	private MimeMessageHelper message;
	private String messageBody;
	private String messageSubject;
	private String[] messageDirectRecipients;
	private String[] messageCopyRecipients;	
	
	/**
	 * Defines the direct recipients of the email message
	 * 
	 * @param recipients Array of direct email recipients
	 */
	public void setDirectRecipients(String[] recipients) {
		this.messageDirectRecipients = recipients;
	}
	
	/**
	 * Returns the defined direct email recipients
	 * 
	 * @return Array of direct email recipients
	 */
	public String[] getDirectRecipients() {
		return this.messageDirectRecipients;
	}
	
	/**
	 * Defines the copy recipients of the email message
	 * 
	 * @param recipients Array of copy email recipients
	 */
	public void setCopyRecipients(String[] recipients) {
		if (recipients != null) {
			this.messageCopyRecipients = recipients;
		}
	}
	
	/**
	 * Returns the defined copy email recipients
	 * 
	 * @return Array of copy email recipients
	 */
	public String[] getCopyRecipients() {
		return this.messageCopyRecipients;
	}
	
	/**
	 * Defines the email message subject
	 * 
	 * @param messageSubject Text which acts as the email message subject
	 */
	public void setSubject(final String messageSubject) {
		this.messageSubject = messageSubject;
	}
	
	/**
	 * Returns the defines email message subject
	 * 
	 * @return Email message Subject
	 */
	public String getSubject() {
		return this.messageSubject;
	}
	
	/**
	 * Defines the email message content
	 * 
	 * @param messageBody Body-Content of the email message
	 */
	public void setMessageContent(final String messageBody) {
		this.messageBody = messageBody;
	}
	
	/**
	 * Returns the defined message body content
	 * 
	 * @return Defined message body content
	 */
	public String getMessageContent() {
		return this.messageBody;
	}
	
	/**
	 * This method is invoked by the JavaMailSender object
	 * 
	 * @see org.springframework.mail.javamail.JavaMailSender
	 */
	@Override
	public void prepare(MimeMessage mimeMessage) throws Exception {
		this.initializeMimeMessageHelper(mimeMessage);
		
		this.message.setTo(this.messageDirectRecipients);
		
		if (this.messageCopyRecipients != null) {
			this.message.setCc(this.messageCopyRecipients);
		}
		
		this.message.setSubject(this.messageSubject);
		
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("applicationName", this.applicationKernel.getConfig("application.name", "My Application"));
		model.put("messageBody", this.messageBody);
		
		this.message.setText(VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine, this.messageLayoutTemplate, "UTF-8", model), true);
		this.message.addInline("bannerCompanyLogo", new ClassPathResource("templates/email/messageLayout/banner-companyLogo.png"));
	}

	/**
	 * Clears all properties that may have been changed via the setter methods.
	 */
	public void clear() {
		this.messageBody 				= null;
		this.messageSubject 			= null;
		this.messageDirectRecipients 	= null;
		this.messageCopyRecipients 		= null;
	}
	
	/**
	 * Initializes and pre-configures a MimeMessageHelper Object.
	 * 
	 * @param mimeMessage MimeMessage Object
	 * @throws Exception If something went wrong
	 * @see org.springframework.mail.javamail.MimeMessageHelper.MimeMessageHelper
	 * @see javax.mail.internet.MimeMessage
	 */
	private void initializeMimeMessageHelper(MimeMessage mimeMessage) throws Exception {
		this.message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
		
		this.message.setFrom(
			new InternetAddress(
				this.coreConfigDao.findOneByPropertyClass(MailFromAddress.class).getProperty().getStringValue(), 
				this.coreConfigDao.findOneByPropertyClass(MailFromAlias.class).getProperty().getStringValue()
			)
		);
		
		this.message.setReplyTo(this.coreConfigDao.findOneByPropertyClass(MailReplyAddress.class).getProperty().getStringValue());
		this.message.setSentDate(new Date());
	}
}
