package com.tandbergtv.workflow.adaptor.handler;


import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.tandbergtv.workflow.adaptor.conf.IHandlerConfiguration;
import com.tandbergtv.workflow.message.HTTPMessage;
import com.tandbergtv.workflow.message.HTTPPayload;
import com.tandbergtv.workflow.message.IMessage;
import com.tandbergtv.workflow.message.WorkflowMessage;
import com.tandbergtv.workflow.message.util.Unmarshaller;
import com.tandbergtv.workflow.util.XMLDocumentUtility;

/**
 * Creates the payload for all submit jobs to the Agility transcoder.
 * 
 * @author Sahil Verma
 */
public class SubmitJobTransformer extends XMLTemplateHandler {
	
	private static final String OUTPUT_TAG_SUFFIX = "-output-dir";
	private static final String OUTPUT_TAG_WPCL_KEY = "format";
	private static final String DEST_DIR_WPCL_KEY = "dest-dir";
	private static final String JOB_PROFILE_WPCL_KEY = "job-profile";
	private static final Logger logger = Logger.getLogger(SubmitJobTransformer.class);
	
	/**
	 * Creates a SubmitJobTransformer
	 */
	public SubmitJobTransformer() {
	}

	/**
	 * Creates a SubmitJobTransformer
	 * @param conf
	 */
	public SubmitJobTransformer(IHandlerConfiguration conf) {
		super(conf);
	}

	/**
	 * @see com.tandbergtv.workflow.adaptor.handler.IHandler#process(com.tandbergtv.workflow.message.IMessage)
	 */
	public IMessage process(IMessage msg) throws HandlerException {
		IMessage ret = null;
		IMessage converted = super.process(msg);
		
		try {
			WorkflowMessage wpcl = getWPCL(msg);
			Document document = XMLDocumentUtility.loadXml(converted.getPayload().getContent());
			
			String profileDir = getJobProfile(wpcl);
			addProfileDir(document, profileDir);
			
			String dir = getDestinationDir(wpcl);
			String outputTag = getOutputTag(wpcl).trim();
			/* Lookup the correct dir node based on the profile */
			addOutputDirNode(document, outputTag + OUTPUT_TAG_SUFFIX, dir);
			
			HTTPPayload payload = new HTTPPayload(XMLDocumentUtility.convertToString(document));
			
			ret = new HTTPMessage(payload);
		} catch (Exception e) {
			throw new HandlerException(e);
		}

		return ret;
	}
	
	/*
	 * Gets the Workflow message (WPCL) from the message. 
	 */
	protected WorkflowMessage getWPCL(IMessage message) throws Exception {
		Document document = XMLDocumentUtility.loadXml(message.getPayload().getContent());
		WorkflowMessage wpcl = Unmarshaller.unmarshal(document);

		return wpcl;
	}
	
	/*
	 * Gets the job profile from the message. 
	 */
	protected String getJobProfile(WorkflowMessage wpcl) {
		return wpcl.getValue(JOB_PROFILE_WPCL_KEY);
	}
	
	/*
	 * Gets the destination dir from the message. 
	 */
	protected String getDestinationDir(WorkflowMessage wpcl) {
		return wpcl.getValue(DEST_DIR_WPCL_KEY);
	}
	
	/*
	 * Gets the output directory tag from the message. 
	 */
	protected String getOutputTag(WorkflowMessage wpcl) {
		return wpcl.getValue(OUTPUT_TAG_WPCL_KEY);
	}
	
	/*
	 * Adds the profile directory to the message.
	 */
	protected void addProfileDir(Document document, String profile) throws HandlerException {
		IHandlerConfiguration conf = getConfiguration();
		
		if (profile == null || profile.length() == 0)
			throw new HandlerException("Job profile is missing");
		
		String key = conf.getParameterValue("PROFILE_DIR_ELEMENT");
		String ext = conf.getParameterValue("JOB_PROFILE_EXT");
		String value = conf.getParameterValue("PROFILE_DIR") + profile + ext;
		
		logger.debug("Setting profile dir " + key + " to " + value);
		
		try {
			Node node = getProfileDirNode(document);

			node.setTextContent(value);
			document.getDocumentElement().appendChild(node);
		} catch (Exception e) {
			throw new HandlerException("Failed to add profile directory to message", e);
		}
	}
	
	/*
	 * Gets the profile directory node from the message. 
	 */
	protected Node getProfileDirNode(Document document) throws Exception {
		XPath xpath = XPathFactory.newInstance().newXPath();
		Node node = (Node)xpath.evaluate("//profile-dir", document, XPathConstants.NODE);
		
		return node;
	}
	
	/*
	 * Adds the output directory tag to the message.
	 */
	protected void addOutputDirNode(Document document, String name, String dir) {
		Node node = document.createElement(name);
		
		node.setTextContent(dir);
		document.getDocumentElement().appendChild(node);
	}
}
