/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.fw.mail;

// Java classes
import java.io.InputStream;
import javax.mail.internet.MimeMessage;

// Library classes
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.Validate;
import org.springframework.core.io.Resource;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.MimeMessagePreparator;

// Framework classes
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.AbstractComponent;
import gov.va.med.fw.service.ServiceDescriptor;
import gov.va.med.fw.service.trigger.TriggerableService;
import gov.va.med.fw.service.trigger.TriggerEvent;

/**
 * Allow e-mails to be sent out asychronously using a message producer.
 * A message producer uses a JMS message queue to which messages are 
 * published and consumed.
 *
 * Project: Framework</br>
 * Created on: 11:26:20 AM </br>
 *
 * @author DNS   LEV
 */
public class AsynchronousMailService extends AbstractComponent implements MailService {

	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 6062056321128902438L;

	/**
	 * An instance of an event router
	 */
	private TriggerableService triggerService = null;
	
	/**
	 * An instance of triggerEventName
	 */
	private String triggerEventName = null;
	
	/**
	 * A default constructor
	 */
	public AsynchronousMailService() {
		super();
	}

	/**
	 * @see gov.va.med.fw.service.AbstractComponent#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		Validate.notNull( this.triggerService, "A trigger service is required" );
		
		// Set a default trigger event name
		if( triggerEventName == null ) {
			StringBuffer tmp = new StringBuffer( ClassUtils.getShortClassName( this.getClass().getName() ) );
			tmp.append( "." )
				.append( ClassUtils.getShortClassName( ServiceDescriptor.class.getName() ) );
			
			// Build a default name "AsynchronousReportService.ServiceDescriptor"
			triggerEventName = tmp.toString();
		}
	}

	/**
	 * @see gov.va.med.fw.mail.MailService#send(java.lang.String, org.springframework.mail.SimpleMailMessage)
	 */
	public void send(String text, SimpleMailMessage template) throws MailException {
		
		Object[] params = new Object[]{text, template};
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	/**
	 * @see gov.va.med.fw.mail.MailService#send(java.lang.String, java.lang.String, org.springframework.mail.SimpleMailMessage)
	 */
	public void send(String text, String attachment, SimpleMailMessage template) throws MailException {
		Object[] params = new Object[]{text, attachment, template};
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	/**
	 * @see gov.va.med.fw.mail.MailService#send(java.lang.String, org.springframework.core.io.Resource, org.springframework.mail.SimpleMailMessage)
	 */
	public void send(String text, Resource resource, SimpleMailMessage template) throws MailException {
		Object[] params = new Object[]{text, resource, template};
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	/**
	 * @see gov.va.med.fw.mail.MailService#send(java.lang.String, org.springframework.core.io.Resource, org.springframework.mail.SimpleMailMessage)
	 */
	public void send(String text, Resource resource, SimpleMailMessage template, String contentType ) throws MailException {
		Object[] params = new Object[]{text, resource, template, contentType };
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}
	
	/**
	 * @see org.springframework.mail.javamail.JavaMailSender#createMimeMessage()
	 */
	public MimeMessage createMimeMessage() {
		return null;
	}

	/**
	 * @see org.springframework.mail.javamail.JavaMailSender#createMimeMessage(java.io.InputStream)
	 */
	public MimeMessage createMimeMessage(InputStream arg0) throws MailException {
		return null;
	}

	/**
	 * @see org.springframework.mail.javamail.JavaMailSender#send(javax.mail.internet.MimeMessage)
	 */
	public void send(MimeMessage mime) throws MailException {
		Object[] params = new Object[]{ mime };
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	public void send(MimeMessage[] mimes) throws MailException {
		Object[] params = new Object[]{ mimes };
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	public void send(MimeMessagePreparator preparator) throws MailException {
		Object[] params = new Object[]{preparator};
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	public void send(MimeMessagePreparator[] preparators) throws MailException {
		Object[] params = new Object[]{preparators};
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	public void send(SimpleMailMessage simple) throws MailException {
		Object[] params = new Object[]{ simple };
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	public void send(SimpleMailMessage[] simple ) throws MailException {
		Object[] params = new Object[]{ simple };
		TriggerEvent event = new TriggerEvent( this.triggerEventName, params );
		try {
			this.triggerService.trigger( event );
		}
		catch( ServiceException e ) {
			throw new MailSendException( "failed to send a message asynchronously", e );
		}
	}

	/**
	 * @param triggerEventName The triggerEventName to set.
	 */
	public void setTriggerEventName(String triggerEventName) {
		this.triggerEventName = triggerEventName;
	}
	
	/**
	 * @param triggerService The triggerService to set.
	 */
	public void setTriggerService(TriggerableService triggerService) {
		this.triggerService = triggerService;
	}
}