/**
 * GetPitchStatusDispatcher.java
 * Created on Jul 29, 2008
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.workflow.adaptor.dispatcher;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.rmi.RemoteException;

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.systinet.wsdl.com.n2bb.manager.webservice.common.Catcher;
import com.systinet.wsdl.com.n2bb.manager.webservice.common.PitchItem;
import com.systinet.wsdl.com.n2bb.manager.webservice.common.ScheduledItem;
import com.systinet.wsdl.com.n2bb.manager.webservice.server.SchedulerService;
import com.systinet.wsdl.com.n2bb.manager.webservice.server.SchedulerService_getAllScheduledPitchDetails_comN2BbManagerWebserviceCommonServiceException_Fault;
import com.systinet.wsdl.com.n2bb.manager.webservice.server.SchedulerService_getCatchers_comN2BbManagerWebserviceCommonServiceException_Fault;
import com.tandbergtv.workflow.adaptor.conf.IDispatcherConfiguration;
import com.tandbergtv.workflow.comm.IDestination;
import com.tandbergtv.workflow.message.IMessage;
import com.tandbergtv.workflow.message.MessageKeyImpl;
import com.tandbergtv.workflow.message.MessageUIDImpl;
import com.tandbergtv.workflow.message.WorkflowMessage;
import com.tandbergtv.workflow.message.WorkflowPayload;
import com.tandbergtv.workflow.message.WorkflowMessage.MessageType;
import com.tandbergtv.workflow.util.XMLDocumentUtility;

/**
 * @author Vlada Jakobac
 * 
 */
public class GetPitchStatusDispatcher extends MediaPathDispatcher {

	private static final Logger logger = Logger
			.getLogger(GetPitchStatusDispatcher.class);

	public GetPitchStatusDispatcher(IDispatcherConfiguration conf,
			IDestination destination) {
		super(conf, destination);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tandbergtv.workflow.adaptor.dispatcher.MediaPathDispatcher#generateResponse(com.tandbergtv.workflow.message.IMessage,
	 *      java.net.URL)
	 */
	@Override
	protected WorkflowMessage generateResponse(IMessage msg, URL url)
			throws DispatcherException {
		logger.debug("payload=" + msg.getPayload().getContent());
		Document doc;
		try {
			doc = XMLDocumentUtility.loadXml(msg.getPayload().getContent());

			String pitchId = null;
			XPath xpath = XPathFactory.newInstance().newXPath();
			Node parameterListNode = (Node) xpath.evaluate(
					"//WFSMessage/MessageBody/ParameterList", doc,
					XPathConstants.NODE);
			if (parameterListNode != null) {
				Node pitchIdNode = (Node) xpath.evaluate(
						"Parameter[@Name='PitchId']", parameterListNode,
						XPathConstants.NODE);
				if (pitchIdNode != null) {
					pitchId = (String) xpath.evaluate("Value", pitchIdNode,
							XPathConstants.STRING);
				}
			}

			Node wfsMessageNode = (Node) xpath.evaluate("//WFSMessage", doc,
					XPathConstants.NODE);

			String messUID = (String) wfsMessageNode.getAttributes()
					.getNamedItem("UID").getTextContent();
			String requestKey = (String) wfsMessageNode.getAttributes()
					.getNamedItem("RequestKey").getTextContent();
			logger.debug("messUID=" + messUID + ", requestKey=" + requestKey);
			WorkflowMessage response = new WorkflowMessage(new MessageUIDImpl(
					messUID), new MessageKeyImpl(requestKey));
			WorkflowPayload payload = (WorkflowPayload) response.getPayload();

			try {
				SchedulerService service = getService(url);
				PitchItem[] pitchItems = getPitchItems(service, pitchId);
				//ignoring duplicate pitchItem ids, getting the first one
				Long pitchStatusLong = pitchItems[0].getStatus();

				setPitchStatusValue(payload, pitchStatusLong);

				// if not SUCCESS, find out which catchers failed
				if (pitchStatusLong.intValue() != MediaPathDispatcher.SUCCESS_FLAG) {
					String failedCatchersNames = getFailedCatchersNames(
							service, pitchItems[0]);
					payload
							.putValue("FailedCatchersNames",
									failedCatchersNames);
				}

				response.setType(MessageType.ack);
			} catch (MediaPathAPIException e) {
				String excMsg = "Error occurred while getting the pitch status for a package: ";
				logger.error(excMsg, e);
				StringWriter writer = new StringWriter();
				e.printStackTrace(new PrintWriter(writer));
				payload.putValue("error-message", e.getMessage());
				payload.putValue("error-stack", writer.toString());
				response.setType(MessageType.nack);
			}
			return response;
		} catch (Exception e) {
			throw new DispatcherException(e);
		}

	}

	private void setPitchStatusValue(WorkflowPayload payload,
			Long pitchStatusLong) {
		String pitchStatus = MediaPathDispatcher.UNKNOWN;
		switch (pitchStatusLong.intValue()) {
			case 0 :
				pitchStatus = MediaPathDispatcher.IN_QUEUE;
				break;
			case 1 :
				pitchStatus = MediaPathDispatcher.IN_PROGRESS;
				break;
			case 2 :
				pitchStatus = MediaPathDispatcher.SUCCESS;
				break;
			case 3 :
				pitchStatus = MediaPathDispatcher.ATTEMPTED;
				break;
			case 4 :
				pitchStatus = MediaPathDispatcher.STOP_REQUESTED;
				break;
			case 5 :
				pitchStatus = MediaPathDispatcher.STOPPED;
				break;
			case 6 :
				pitchStatus = MediaPathDispatcher.FAILED;
				break;
			case 7 :
				pitchStatus = MediaPathDispatcher.DELETED;
				break;
			case 8 :
				pitchStatus = MediaPathDispatcher.ENCRYPTING;
				break;
			default :
				pitchStatus = MediaPathDispatcher.UNKNOWN;
				break;
		}
		payload.putValue("PitchStatus", pitchStatus);
	}

	private String getFailedCatchersNames(SchedulerService service,
			PitchItem pitchItem) throws MediaPathAPIException {
		String failedCatchersNames = "";
		ScheduledItem[] schItems = pitchItem.getItems();
		Catcher[] catchers;
		try {
			catchers = service.getCatchers();
		} catch (SchedulerService_getCatchers_comN2BbManagerWebserviceCommonServiceException_Fault e) {
			throw new MediaPathAPIException(e);
		} catch (RemoteException e) {
			throw new MediaPathAPIException(e);
		}
		for (int i = 0; i < schItems.length; i++) {
			if (schItems[i].getStatus().intValue() != MediaPathDispatcher.SUCCESS_FLAG) {
				String catcherName = getCatcherNameById(catchers, schItems[i].getCatcher());
				if (!catcherName.equals(""))
					failedCatchersNames = failedCatchersNames + catcherName + ",";
				
			}
		}
		// remove the last comma
		if (failedCatchersNames.length() > 0)
			failedCatchersNames = failedCatchersNames.substring(0, failedCatchersNames.length() - 1);
		logger.debug("failedCatchersNames=" + failedCatchersNames);
		return failedCatchersNames;
	}

	private String getCatcherNameById(Catcher[] catchers, Long catcherId)
			throws MediaPathAPIException {
		String catcherName = "";
		for (int i = 0; i < catchers.length; i++) {
			if (catchers[i].getId().longValue() == catcherId.longValue()) {
				catcherName = catchers[i].getDisplayName();
				break;
			}
		}
		return catcherName;
	}

	private PitchItem[] getPitchItems(SchedulerService service, String pitchId)
			throws MediaPathAPIException {

		long[] pitchIds = new long[1];
		pitchIds[0] = Long.valueOf(pitchId);
		try {
			return service.getAllScheduledPitchDetails(pitchIds);
		} catch (SchedulerService_getAllScheduledPitchDetails_comN2BbManagerWebserviceCommonServiceException_Fault e) {
			throw new MediaPathAPIException(e);
		} catch (RemoteException e) {
			throw new MediaPathAPIException(e);
		}

	}

}
