package com.tandbergtv.workflow.message;

import org.jbpm.graph.exe.ExecutionContext;

import com.tandbergtv.workflow.message.WorkflowMessage.MessageType;

/**
 * This class is a factory for creating WorkflowMessages
 * 
 * @author Raj Prakash Govindarajan
 * @author Sahil Verma
 */
public abstract class WorkflowMessageFactory
{
	/* FIXME Hard-coded */
	private static final String FACTORY_IMPL = "com.tandbergtv.workflow.message.impl.WorkflowMessageFactoryImpl";
	
	private static WorkflowMessageFactory newInstance()
	{
		String className = FACTORY_IMPL;
		Class<?> clazz;
		WorkflowMessageFactory instance = null;
		
		try
		{
			clazz = WorkflowMessageFactory.class.getClassLoader().loadClass(className);

			instance = (WorkflowMessageFactory)clazz.newInstance();
		}
		catch (Exception e)
		{
			throw new RuntimeException("Factory class " + className + " could not be instantiated", e);
		}
		
		return instance;
	}
	
	/**
	 * Creates a Workflow Message of type control. Sets the Message UID with the input uid value.
	 * Sets the default source and response destination (read from the Application Properties), and
	 * uses an empty payload.
	 * 
	 * @param uid
	 *            Message UID
	 *            
	 * @return Workflow Message
	 */
	public static WorkflowMessage createControlMessage(String uid)
	{
		return newInstance().createControlMessageImpl(uid);
	}
	
	/**
	 * This method sets the Message Key to the message using information from execution context.
	 * 
	 * @param uid Message UID
	 * @param ec Execution Context
	 * @return Workflow Message
	 * 
	 */
	public static WorkflowMessage createControlMessage(String uid, ExecutionContext ec)
	{
		return newInstance().createControlMessageImpl(uid, ec);
	}

	/**
	 * Creates a workflow message of type ack. Copies message uid and key from the parameter
	 * message. Sets default source and empty payload for the message
	 * 
	 * @param message
	 *            Workflow Message
	 * @return Workflow Message
	 */
	public static WorkflowMessage createAckMessage(WorkflowMessage message)
	{
		return newInstance().createWorkflowMessageImpl(message.getMessageUID(), message.getKey(), MessageType.ack);
	}
	
	/**
	 * Creates a workflow message of type nack. Copies message uid and key from the parameter
	 * message. Sets default source and empty payload for the message.
	 * 
	 * @param message
	 *            Workflow Message
	 * @return Workflow Message
	 * 
	 */
	public static WorkflowMessage createNackMessage(WorkflowMessage message)
	{
		return newInstance().createWorkflowMessageImpl(message.getMessageUID(), message.getKey(), MessageType.nack);
	}
	
	/**
	 * Creates a message of type control
	 * 
	 * @param uid
	 * @return the newly created message
	 */
	protected abstract WorkflowMessage createControlMessageImpl(String uid);
	
	/**
	 * Creates a message of type control with a generated correlation id
	 * 
	 * @param uid
	 * @param ec
	 * @return the newly created message
	 */
	protected abstract WorkflowMessage createControlMessageImpl(String uid, ExecutionContext ec);
	
	/**
	 * Creates a message of the specified uid, type and correlation id
	 * 
	 * @param uid
	 * @param key
	 * @param type
	 * @return the newly created message
	 */
	protected abstract WorkflowMessage createWorkflowMessageImpl(IMessageUID uid, IMessageKey key, MessageType type);
}
