/**
 * WorkOrderCreator.java
 * Created on Jun 5, 2008
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.watchpoint.pmm.job.execution;

import static com.tandbergtv.watchpoint.pmm.job.execution.WorkOrderCreationConstants.TEMPLATE_NAME;
import static com.tandbergtv.watchpoint.pmm.job.execution.WorkOrderCreationConstants.TEMPLATE_PARAMTERS;
import static com.tandbergtv.watchpoint.pmm.job.execution.WorkOrderCreationConstants.WORK_ORDER_PRIORITY;

import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Document;

import com.tandbergtv.watchpoint.pmm.util.XMLDocumentUtility;
import com.tandbergtv.workflow.comm.routing.IRoutingService;
import com.tandbergtv.workflow.comm.routing.RoutingServiceFactory;
import com.tandbergtv.workflow.core.TaskVariable;
import com.tandbergtv.workflow.core.WorkflowTemplate;
import com.tandbergtv.workflow.core.service.ServiceRegistry;
import com.tandbergtv.workflow.driver.service.ITemplateLoaderService;
import com.tandbergtv.workflow.message.IMessage;
import com.tandbergtv.workflow.message.MessageImpl;
import com.tandbergtv.workflow.message.StringPayload;
import com.tandbergtv.workflow.message.WPCLCommand;
import com.tandbergtv.workflow.message.WorkflowMessage;
import com.tandbergtv.workflow.message.WorkflowMessageFactory;
import com.tandbergtv.workflow.message.WorkflowPayload;
import com.tandbergtv.workflow.message.util.Marshaller;

/**
 * This class creates and starts a work order using the info passed in the map. It expects the
 * template name, priority and parameters for the template in the map.
 * 
 * @author spuranik
 */
public class WorkOrderCreator implements IJobExecutor {

	private static String WORK_ORDER_MESSAGE_UID = "PM0111";

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tandbergtv.watchpoint.pmm.job.execution.IJobExecutor#execute(java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	public void execute(Map<String, Object> info) {
		// template name
		String templateName = (String) info.get(TEMPLATE_NAME);

		// priority
		String priority = ((String) info.get(WORK_ORDER_PRIORITY)).toUpperCase();

		// template variables
		Map<String, Object> variables = (Map<String, Object>) info.get(TEMPLATE_PARAMTERS);

		ServiceRegistry registry = ServiceRegistry.getDefault();
		WorkflowTemplate definition = registry.lookup(ITemplateLoaderService.class)
				.getTemplateByName(templateName);

		Map<String, Object> vars = prepareTemplateVariables(definition, variables);
		WorkflowMessage message = createWorkFlowMessage(templateName, priority, vars);
		IRoutingService router = RoutingServiceFactory.newInstance().createRoutingService();
		
		try {
			IMessage msg = convert(message);

			router.send(msg);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * The variable list prepared by the job module has the mapped name for the template variable.
	 * When creating a work order the variable name (and not the mapped name) is required by the
	 * template So this method prepares a map of variable names from the template's variable list to
	 * variable values given by the user via job creation.
	 * 
	 * @param definition
	 *            process definition for the selected template to get the start variables.
	 * @return map of template variable name -> value
	 */
	private Map<String, Object> prepareTemplateVariables(WorkflowTemplate definition,
			Map<String, Object> variables) {
		Map<String, Object> templateVariables = new HashMap<String, Object>();

		for (TaskVariable variable : definition.getStartTaskVariables()) {
			// insert only those variables which have values or else the message may
			// not be saved in the db.
			String varValue = (String)variables.get(variable.getMappedName());
			if (varValue != null && varValue.trim().length() > 0) {
				templateVariables.put(variable.getVariableName(), varValue);
			}
		}

		return templateVariables;
	}

	/**
	 * creates a work flow message for this work order creation This is used only for logging
	 * purposes.
	 * 
	 * @param variables
	 *            list of template variables with their names and values
	 * @return workflow message object
	 */
	private WorkflowMessage createWorkFlowMessage(String templateName, String priority,
			Map<String, Object> variables) {
		WorkflowMessage message = WorkflowMessageFactory
				.createControlMessage(WORK_ORDER_MESSAGE_UID);
		WPCLCommand command = new WPCLCommand("create");

		command.addParameter("priority", priority);
		command.addParameter("_template", templateName);

		message.setCommand(command);

		WorkflowPayload payload = message.getPayload();

		for (String name : variables.keySet()) {
			String value = variables.get(name).toString();

			payload.putValue(name, value);
		}

		return message;
	}
	
	private static IMessage convert(WorkflowMessage message) throws Exception {
		Document document = Marshaller.newMarshaller().marshal(message);
		StringPayload payload = new StringPayload(XMLDocumentUtility.convertToString(document));

		return new MessageImpl(payload, message.getAttachment());
	}
}
