/*
 * Created on Aug 27, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.watchpoint.pmm.web.actions.title;

import static com.tandbergtv.watchpoint.pmm.entities.ContainerType.PARTNER;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.tandbergtv.watchpoint.pmm.entities.AssetList;
import com.tandbergtv.watchpoint.pmm.entities.IAssetList;
import com.tandbergtv.watchpoint.pmm.entities.IContainer;
import com.tandbergtv.watchpoint.pmm.entities.ProgressItem;
import com.tandbergtv.watchpoint.pmm.entities.Schedule;
import com.tandbergtv.watchpoint.pmm.entities.Title;
import com.tandbergtv.watchpoint.pmm.entities.TitleListType;
import com.tandbergtv.watchpoint.pmm.web.formbeans.title.TitleActivity;
import com.tandbergtv.watchpoint.pmm.web.formbeans.title.TitleForm;
import com.tandbergtv.watchpoint.pmm.web.formbeans.title.TitleSchedule;
import com.tandbergtv.workflow.core.service.ServiceRegistry;
import com.tandbergtv.workflow.core.service.cache.ICacheService;

/**
 * Action that allows viewing of the history of a Title
 * 
 * @author Vijay Silva
 */
public class ViewTitleActivityAction extends TitleAction {

	/**
	 * Action to prepare the History for a Title
	 * 
	 * @param actionMapping
	 * @param actionForm
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ActionForward viewActivity(ActionMapping actionMapping, ActionForm actionForm,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		TitleForm form = (TitleForm) actionForm;

		/* This is copy all the title data to the form */
		this.populateForm(form, false);

		/* Build the Title History */
		TitleActivity titleActivity = this.buildTitleActivity(form.getTitle());
		form.setTitleActivity(titleActivity);

		/* Sort the Title Activity based on the view requirements */
		this.sortTitleActivity(titleActivity);

		/* Forward to the Title History page */
		return actionMapping.findForward("view");
	}

	/* Build the Title History object given the Title */
	private TitleActivity buildTitleActivity(Title title) {
		TitleActivity titleActivity = new TitleActivity();

		/* Build the list of title schedules */
		this.buildTitleSchedules(title, titleActivity);

		/* Build the map of progress items sorted by asset list id */
		Map<Long, List<ProgressItem>> progressItemMap = this.buildProgressItemMap(title);

		/* Build the History for each Asset List Id */
		for (Long key : progressItemMap.keySet()) {
			AssetList assetList = this.getAssetList(title, key);

			/* Check if the asset list is a pitch schedule */
			if (assetList != null && assetList.getType() == TitleListType.PITCH) {
				Schedule schedule = (Schedule) assetList;
				long contextId = schedule.getContextID();

				TitleSchedule scheduleActivity = new TitleSchedule();
				scheduleActivity.setSchedule(schedule);
				scheduleActivity.setProgressHistory(progressItemMap.get(key));
				scheduleActivity.setContainerContextId(contextId);
				scheduleActivity.setContainer(this.getContainer(contextId));

				titleActivity.getOutgoingActivity().add(scheduleActivity);
			}

			/* The asset list is not a pitch, gather all progress items as incoming activity */
			else {
				TitleSchedule scheduleActivity = titleActivity.getIncomingActivity();
				if (scheduleActivity == null) {
					scheduleActivity = new TitleSchedule();
					titleActivity.setIncomingActivity(scheduleActivity);
				}

				scheduleActivity.getProgressHistory().addAll(progressItemMap.get(key));
			}
		}

		return titleActivity;
	}

	/* Build the title schedule objects and set them in the activity object given the title */
	private void buildTitleSchedules(Title title, TitleActivity titleActivity) {
		List<TitleSchedule> titleSchedules = titleActivity.getTitleSchedules();
		if (title.getTitlelists() == null) {
			return;
		}

		for (IAssetList assetList : title.getTitlelists()) {
			TitleListType type = assetList.getType();

			/* Build the Title Schedule object for the Pitch Schedule */
			if (type == TitleListType.PITCH) {
				TitleSchedule titleSchedule = new TitleSchedule();
				Schedule schedule = (Schedule) assetList;
				titleSchedule.setSchedule(schedule);
				titleSchedule.setContainerContextId(schedule.getContextID());
				titleSchedule.setContainer(this.getContainer(schedule.getContextID()));

				titleSchedules.add(titleSchedule);
			}

			/* Build the Title Schedule object for the Planner */
			else if (type == TitleListType.PLANNER) {
				TitleSchedule titleSchedule = new TitleSchedule();
				Schedule schedule = (Schedule) assetList;
				titleSchedule.setSchedule(schedule);
				Long contextId = this.getPartnerContextId(schedule.getSourcePartnerID());
				titleSchedule.setContainerContextId(contextId);
				titleSchedule.setContainer(this.getContainer(contextId));

				titleSchedules.add(titleSchedule);
			}
		}
	}

	/*
	 * Builds a map of the schedule Id to list of progress items for that schedule Id. The schedule
	 * Id key will be null for progress items not associated with any schedule.
	 */
	private Map<Long, List<ProgressItem>> buildProgressItemMap(Title title) {
		Map<Long, List<ProgressItem>> progressItemMap = new HashMap<Long, List<ProgressItem>>();

		if (title.getProgressItems() == null)
			return progressItemMap;

		/* Sort all Progress Items by Asset List Id */
		for (ProgressItem progressItem : title.getProgressItems()) {
			Long key = progressItem.getAssetListId();
			List<ProgressItem> value = progressItemMap.get(key);
			if (value == null) {
				value = new ArrayList<ProgressItem>();
				progressItemMap.put(key, value);
			}
			value.add(progressItem);
		}

		return progressItemMap;
	}

	/* Find the matching Asset List from the given list */
	private AssetList getAssetList(Title title, Long assetListId) {
		if (assetListId == null || title.getTitlelists() == null)
			return null;

		/* Find the matching Asset List */
		AssetList match = null;
		for (IAssetList assetList : title.getTitlelists()) {
			if (assetList.getId().equals(assetListId)) {
				match = AssetList.class.cast(assetList);
				break;
			}
		}

		return match;
	}

	/* Gets the Container given the context Id */
	@SuppressWarnings("unchecked")
	private IContainer getContainer(long contextId) {
		ServiceRegistry registry = ServiceRegistry.getDefault();
		ICacheService<IContainer> cache = (ICacheService<IContainer>) registry
				.lookup("Container Cache");
		return cache.get(contextId);
	}

	/* Gets the Partner given the Partner Id */
	@SuppressWarnings("unchecked")
	private Long getPartnerContextId(long partnerId) {
		Long partnerContextId = null;

		ServiceRegistry registry = ServiceRegistry.getDefault();
		ICacheService<IContainer> cache = (ICacheService<IContainer>) registry
				.lookup("Container Cache");
		for (Serializable key : cache.getKeys()) {
			IContainer container = cache.get(key);
			long containerId = container.getContainerId();
			if (container.getContainerType() == PARTNER && containerId == partnerId) {
				partnerContextId = (Long) key;
				break;
			}
		}

		return partnerContextId;
	}

	/*
	 * Sorts the different sections of the title activity: Title Schedules, Incoming Activity, and
	 * Outgoing Activity
	 */
	private void sortTitleActivity(TitleActivity titleActivity) {
		/* Sort the Title Schedules */
		List<TitleSchedule> titleSchedules = titleActivity.getTitleSchedules();
		if (titleSchedules != null)
			Collections.sort(titleSchedules, new TitleScheduleComparator());

		/* Sort the Incoming Title Activity */
		this.sortProgressHistory(titleActivity.getIncomingActivity());

		/* Sort the Outgoing Title Activity */
		List<TitleSchedule> outgoingActivity = titleActivity.getOutgoingActivity();
		if (outgoingActivity != null) {
			for (TitleSchedule activity : outgoingActivity) {
				this.sortProgressHistory(activity);
			}

			Collections.sort(outgoingActivity, new TitleScheduleComparator());
		}
	}

	/* Sort the Progress Item History by date in the Title Schedule Activity object */
	private void sortProgressHistory(TitleSchedule activity) {
		if (activity != null && activity.getProgressHistory() != null) {
			Collections.sort(activity.getProgressHistory(), new ProgressItemComparator());
		}
	}

	/* Internal class for comparing Title Schedule objects */
	private class TitleScheduleComparator implements Comparator<TitleSchedule> {
		/* Compares the schedule dates for 2 input schedules. */
		public int compare(TitleSchedule o1, TitleSchedule o2) {
			Date d1 = o1.getSchedule().getDate();
			Date d2 = o2.getSchedule().getDate();

			return d2.compareTo(d1);
		}
	}

	/* Internal class for comparing Progress Item objects */
	private class ProgressItemComparator implements Comparator<ProgressItem> {
		/* Compares the dates for 2 progress items. */
		public int compare(ProgressItem o1, ProgressItem o2) {
			Date d1 = o1.getTimestamp();
			Date d2 = o2.getTimestamp();

			return d2.compareTo(d1);
		}
	}
}
