/**
 * SetFilePropertiesMessageHandler.java
 * Created on Jul 7, 2009
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.watchpoint.pmm.communication.handlers;

import com.tandbergtv.cms.portal.util.transaction.Transactional;
import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.model.Field;
import com.tandbergtv.metadatamanager.model.FieldName;
import com.tandbergtv.metadatamanager.model.File;
import com.tandbergtv.watchpoint.communication.Util;
import com.tandbergtv.watchpoint.pmm.communication.HandlerErrorCode;
import com.tandbergtv.watchpoint.pmm.communication.MessageHandler;
import com.tandbergtv.watchpoint.pmm.communication.MessageHandlerException;
import com.tandbergtv.watchpoint.pmm.core.ITitleStatusService;
import com.tandbergtv.watchpoint.pmm.core.TitleValidationException;
import com.tandbergtv.watchpoint.pmm.entities.Title;
import com.tandbergtv.watchpoint.pmm.title.ITitleService;
import com.tandbergtv.watchpoint.pmm.title.TitleStatusService;
import com.tandbergtv.watchpoint.pmm.util.ProgressStatusHelper;
import com.tandbergtv.workflow.core.service.ServiceRegistry;
import com.tandbergtv.workflow.message.IMessageKey;
import com.tandbergtv.workflow.message.IMessageUID;
import com.tandbergtv.workflow.message.WorkflowMessage;
import com.tandbergtv.workflow.message.WorkflowMessage.MessageType;

/**
 * @author Vlada Jakobac
 * 
 */
public class SetFilePropertiesMessageHandler implements MessageHandler {

	private static final String MATERIAL_ID_XPATH = "/tns:Fields/tns:CustomFields/tns:CustomField[@name=MaterialId]/@value";
	private static final String ENCODE_PROFILE_XPATH = "/tns:Fields/tns:CustomFields/tns:CustomField[@name=EncodeProfile]/@value";
	private static final String ENCODE_FORMAT_XPATH = "/tns:Fields/tns:CustomFields/tns:CustomField[@name=EncodeFormat]/@value";
	private static final String LOOKUP_KEY_XPATH = "/tns:Fields/tns:CustomFields/tns:CustomField[@name=LookupKey]/@value";
	private static final String LOOKUP_KEY = "lookupKey";
	private static final String HEIGHT = "height";
	private static final String WIDTH = "width";
	private static final String FILE_SIZE = "fileSize";
	private static final String MIME_TYPE = "mimeType";
	private static final String FILE_NAME = "fileName";
	private static final String DURATION = "duration";
	private static final String ASPECTRATIO = "aspectratio";
	private static final String BITRATE = "bitrate";
	private static final String RESOLUTION = "resolution";
	private static final String MATERIAL_ID = "materialId";
	private static final String ENCODE_PROFILE = "encodeProfile";
	private static final String ENCODE_FORMAT = "encodeFormat";
	private static final String TITLE_ID = "titleId";
	private static final String FILE_URI = "fileURI";
	private static final String FILE_ASSET_ID = "fileAssetId";
	private static final String RESULT = "result";
	private static final String SUCCESS = "SUCCESS";

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.tandbergtv.watchpoint.pmm.communication.MessageHandler#handleMessage
	 * (com.tandbergtv.workflow.message.WorkflowMessage)
	 */
	@Override
	@Transactional
	public WorkflowMessage handleMessage(WorkflowMessage message)
			throws Exception {
		Util.validateRequired(message, TITLE_ID, FILE_URI, FILE_ASSET_ID);

		Long titleId = Util.getLongValue(message, TITLE_ID);
		String fileURI = Util.getStringValueTrimmed(message, FILE_URI);
		Long fileAssetId = Util.getLongValue(message, FILE_ASSET_ID);

		String encodeFormat = Util
				.getStringValueTrimmed(message, ENCODE_FORMAT);
		String encodeProfile = Util.getStringValueTrimmed(message,
				ENCODE_PROFILE);
		String materialId = Util.getStringValueTrimmed(message, MATERIAL_ID);
		String resolution = Util.getStringValueTrimmed(message, RESOLUTION);
		String bitrate = Util.getStringValueTrimmed(message, BITRATE);
		String aspectratio = Util.getStringValueTrimmed(message, ASPECTRATIO);
		String duration = Util.getStringValueTrimmed(message, DURATION);
		String fileName = Util.getStringValueTrimmed(message, FILE_NAME);
		String mimeType = Util.getStringValueTrimmed(message, MIME_TYPE);
		String fileSize = Util.getStringValueTrimmed(message, FILE_SIZE);
		String width = Util.getStringValueTrimmed(message, WIDTH);
		String height = Util.getStringValueTrimmed(message, HEIGHT);
		String lookupKey = Util.getStringValueTrimmed(message, LOOKUP_KEY);
		String sourceComponentName = Util.getStringValueTrimmed(message, "sourceComponentName");  
		String sourceEntityName = Util.getStringValueTrimmed(message, "sourceEntityName");
		String sourceId = Util.getStringValueTrimmed(message, "sourceId");

		/* Get the Service Registry to allow fetching of the title */
		ServiceRegistry registry = ServiceRegistry.getDefault();
		ITitleService service = registry.lookup(ITitleService.class);

		/* Get the Title using the Service */
		Title title = null;
		try {
			title = service.getTitleForUpdate(titleId);
			
		} catch (Exception e) {
			String msg = "Failed to read the Title from the persistence service, error: "
					+ e.getMessage();
			throw new MessageHandlerException(
					HandlerErrorCode.OBJECT_NOT_PRESENT, msg, e);
		}

		if (title == null) {
			String msg = "Did not get a Title from the persistence service.";
			throw new MessageHandlerException(
					HandlerErrorCode.OBJECT_NOT_PRESENT, msg);
		}

		/* Get the matching asset from the title */
		Asset groupAsset = title.getAsset();
		if (groupAsset == null) {
			String msg = "Did not get a group object for a given title.";
			throw new MessageHandlerException(
					HandlerErrorCode.OBJECT_NOT_PRESENT, msg);
		}

		/* Find the asset file with the given fileAssetId */
		Asset targetAsset = null;
		for (Asset asset : groupAsset.getAllDescendantItems(true)) {
			if (!(asset instanceof File))
				continue;
			if (asset.getId() == fileAssetId) {
				targetAsset = asset;
				break;
			}
		}
		if (targetAsset == null) {
			String msg = "Did not get an item object for a given fileAssetId.";
			throw new MessageHandlerException(
					HandlerErrorCode.OBJECT_NOT_PRESENT, msg);
		}
		
		/* If there's any file with the same lookupKey, set its lookupKey value to blank */
		if (lookupKey != null && !lookupKey.equals("")){
			for (Asset asset : groupAsset.getAssetsParent(targetAsset).getAllDescendantItems(true)) {
				if (!(asset instanceof File))
					continue;

				Field lookupKeyField = asset.getFirstField(LOOKUP_KEY_XPATH);
				if (lookupKeyField != null && lookupKeyField.getTypedValue().equals(lookupKey)){
					lookupKeyField.setValue("");
					
				}
			}

		}

		updateField(targetAsset, FieldName.FILE_URL.toString(), fileURI);
		updateField(targetAsset, ENCODE_FORMAT_XPATH, encodeFormat);
		updateField(targetAsset, ENCODE_PROFILE_XPATH, encodeProfile);
		updateField(targetAsset, MATERIAL_ID_XPATH, materialId);
		updateField(targetAsset, LOOKUP_KEY_XPATH, lookupKey);
		updateField(targetAsset, FieldName.RESOLUTION.toString(), resolution);
		updateField(targetAsset, FieldName.BITRATE.toString(), bitrate);
		updateField(targetAsset, FieldName.ASPECTRATIO.toString(), aspectratio);
		updateField(targetAsset, FieldName.DURATION.toString(), duration);
		updateField(targetAsset, FieldName.FILE_NAME.toString(), fileName);
		updateField(targetAsset, FieldName.MIME_TYPE.toString(), mimeType);
		if (fileSize == null || fileSize.equals(""))
			fileSize = new java.io.File(fileURI).length() + "";
		updateField(targetAsset, FieldName.FILE_SIZE.toString(), fileSize);
		updateField(targetAsset, FieldName.WIDTH.toString(), width);
		updateField(targetAsset, FieldName.HEIGHT.toString(), height);
		

		try {
			service.update(title, sourceComponentName, sourceEntityName, sourceId);
		} catch (TitleValidationException e) {
			// If there were any validations that failed and prevented the title
			// from being persisted, try to save in the DRAFT status. NOTE: this
			// could also fail if validations failed in the DRAFT status. Then
			// there is nothing much we can do.
			
			// Before saving the title as draft, validate it as draft
			service.validate(title, true);
			service.saveAsDraft(title);
			// validation has failed at this point, no matter what the reason is.
			ITitleStatusService statusService = new TitleStatusService();
			statusService.sendStatus(title, ProgressStatusHelper.VALIDATION_FAILURE, e.getMessage(),
					false, sourceComponentName, sourceEntityName, sourceId);
		}

		/* Build the response Workflow Message */
		IMessageUID uid = message.getMessageUID();
		IMessageKey key = message.getKey();
		WorkflowMessage response = new WorkflowMessage(uid, key, MessageType.ack);
		response.putValue(RESULT, SUCCESS);

		return response;
	}

	private void updateField(Asset asset, String ttvXPath, String value) {
		if (value != null) {
			Field field = asset.getFirstField(ttvXPath);
			if (field != null)
				field.setValue(value);
			else
				asset.addField(new Field(ttvXPath, value));
		}

	}
}
