package com.tandbergtv.watchpoint.pmm.web.actions.title;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import com.tandbergtv.watchpoint.pmm.title.TitleServiceException;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleProvider;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleProviderRegistry;
import com.tandbergtv.watchpoint.pmm.util.validation.ValidationMessage;
import com.tandbergtv.watchpoint.pmm.web.formbeans.title.TitleForm;
import com.tandbergtv.watchpoint.pmm.web.title.TitleExternalKeySerializer;
import com.tandbergtv.watchpoint.pmm.web.util.TitleFacade;
import com.tandbergtv.workflow.core.service.ServiceRegistry;

public class ViewTitleAction extends TitleAction {

	/* The Logger */
	private static final Logger logger = Logger.getLogger(ViewTitleAction.class);
	
	private static final String FORWARD_VIEW_PAGE = "view";

	private static final String FORWARD_ERROR_PAGE = "error";
	
	public ActionForward view(ActionMapping actionMapping, ActionForm actionForm,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		TitleForm titleForm = (TitleForm) actionForm;
		
		populateListOptions(titleForm);

		populateForm(titleForm, false);
		
		return actionMapping.findForward(FORWARD_VIEW_PAGE);
	}

	/**
	 * View a Title fetched from an External Source. 
	 * @param actionMapping
	 * @param actionForm
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ActionForward viewExternal(ActionMapping actionMapping, ActionForm actionForm,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		TitleForm titleForm = (TitleForm) actionForm;
		
		populateListOptions(titleForm);

		try {
			populateForm(titleForm, true);
		} catch (TitleServiceException e) {
			logger.error("Failed to get external title for view.", e);

			/* Update the form */
			this.updateForm(titleForm);

			/* Store the error message */
			ActionMessages messages = new ActionMessages();
			ValidationMessage validationMessage = e.getFailureMessage();
			String key = validationMessage.getCode();
			Object[] values = validationMessage.getProperties().toArray();
			ActionMessage actionMessage = new ActionMessage(key, values);
			messages.add("Title.ExternalViewError", actionMessage);
			this.saveMessages(request, messages);

			return actionMapping.findForward(FORWARD_ERROR_PAGE);
		}

		return actionMapping.findForward(FORWARD_VIEW_PAGE);
	}

	private void populateListOptions(TitleForm form) throws Exception {
		form.setTypes(TitleFacade.getSpecifications());
		form.setAssetDBs(TitleFacade.getTitleProviderInstances(form.getType()));
	}

	/* Used when updating the form in case the external title could not be found */
	private void updateForm(TitleForm titleForm) {
		/* Set the External Source Name for the title */
		String externalSourceId = titleForm.getAssetDB();
		String externalSourceName = "";
		if (externalSourceId != null && externalSourceId.trim().length() > 0) {
			ServiceRegistry serviceRegistry = ServiceRegistry.getDefault();
			ITitleProviderRegistry registry = serviceRegistry.lookup(ITitleProviderRegistry.class);
			ITitleProvider provider = registry.getProviderForTitle(externalSourceId);
			externalSourceName = provider.getProviderInstance(externalSourceId).getName();
		}
		titleForm.setAssetDBName(externalSourceName);
		
		/* Ensure that the external key is readable */
		String updatedKey = this.describeTitleExternalKey(titleForm.getExternalKey());
		titleForm.setExternalKey(updatedKey);
	}

	/* Get a String representation of the Title External Key */
	private String describeTitleExternalKey(String externalKey) {
		try {
			TitleExternalKeySerializer serializer = TitleExternalKeySerializer.newInstance();
			Map<String, String> externalKeys = serializer.deserialize(externalKey);

			StringBuilder buf = new StringBuilder();
			boolean isFirst = true;
			for (String key : externalKeys.keySet()) {
				String value = externalKeys.get(key);

				if (isFirst)
					isFirst = false;
				else
					buf.append(", ");

				buf.append(key);
				buf.append(": ");
				buf.append(value);
			}

			return buf.toString();
		} catch (Exception e) {
			logger.warn("Failed to parse the Title external key: " + externalKey
					+ " when creating displayable key.", e);
			return externalKey;
		}
	}
}
