/*
 * TitleProgressBean.java
 * Created Jun 8, 2008
 * Copyright (c) TANDBERG Television 2007-2008
 */
package com.tandbergtv.watchpoint.pmm.web.title;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

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.schedule.ScheduleRuntimeException;
import com.tandbergtv.watchpoint.pmm.web.schedule.PartnerBean;
import com.tandbergtv.workflow.web.util.CommonUtils;

/**
 * Represents a title with 0 or more progress items
 * 
 * @author Sahil Verma
 */
public class TitleProgressBean extends TitleBean implements Comparable<TitleProgressBean> {

	protected Collection<ProgressItem> progressItems;

	private static final String PROGRESS = "progress";

	protected ScheduleData source;

	protected Collection<ScheduleData> destinations;

	/**
	 * Creates a TitleProgressBean
	 * @param title
	 */
	public TitleProgressBean(Title title, Collection<ProgressItem> progressItems) {
		super(title);
		this.progressItems = progressItems;
		// sort in descending order so the latest progress item is read first.
		Collections.sort((List<ProgressItem>)progressItems, new Comparator<ProgressItem>() {
			public int compare(ProgressItem i1, ProgressItem i2) {
				return i1.getTimestamp().before(i2.getTimestamp()) ? 1 : -1;
			}
		});
		this.destinations = new LinkedList<ScheduleData>();
	}

	public boolean getIsProgress(String parameter) {
		return (parameter.startsWith(PROGRESS));
	}

	public boolean getIsMetadata(String parameter) {
		return (!parameter.startsWith(PROGRESS));
	}

	public Long getSourceId() {
		if (this.source != null)
			return this.source.getId();

		return null;
	}

	/**
	 * Returns the name of the source
	 * 
	 * @return
	 */
	public String getSourceName() {
		if (this.source != null)
			return this.source.partner.getName();

		return null;
	}

	/**
	 * Returns the planner id
	 * 
	 * @return
	 */
	public String getPlannerId() {
		if (this.source != null)
			return this.source.schedule.getId().toString();

		return null;
	}

	/**
	 * Returns the arrival date of the planner containing this title
	 * 
	 * @return
	 */
	public String getArrivalDate() {
		if (this.source == null)
			return null;

		return CommonUtils.formatDate(this.source.schedule.getDate());
	}

	/**
	 * @return
	 */
	public Collection<ScheduleData> getDestinations() {
		return this.destinations;
	}

	/**
	 * Adds a planner
	 * 
	 * @param planner the planner
	 * @param source
	 */
	public void addPlanner(Schedule planner, PartnerBean sourcePartner) {
		if (planner.getType() != TitleListType.PLANNER)
			throw new ScheduleRuntimeException(planner + " is not a planner?");

		Collection<ProgressItem> progressItems = new ArrayList<ProgressItem>();

		for (ProgressItem progress : title.getProgressItems()) {
			if (planner.getId().equals(progress.getAssetListId()))
				progressItems.add(progress);
		}

		this.source = new ScheduleData(planner, sourcePartner, progressItems);
	}

	/**
	 * Gets a description for the Planner
	 * 
	 * @return A description specifying the source partner /service name for planner and the planner
	 *         date
	 */
	public String getPlannerDescription() {
		return (this.source != null) ? this.getSourceName() + " : " + this.getArrivalDate() : null;
	}

	/**
	 * Adds a pitch schedule
	 * 
	 * @param pitch
	 * @param destination
	 */
	public void addPitch(Schedule pitch, PartnerBean destination) {
		if (pitch.getType() != TitleListType.PITCH)
			throw new ScheduleRuntimeException(pitch + " is not a pitch?");

		Collection<ProgressItem> progressItems = new ArrayList<ProgressItem>();

		for (ProgressItem progress : title.getProgressItems()) {
			if (pitch.getId().equals(progress.getAssetListId()))
				progressItems.add(progress);
		}

		this.destinations.add(new ScheduleData(pitch, destination, progressItems));
	}

	/**
	 * Just a placeholder text for the URL to the processes that have sent progress for this title
	 * 
	 * @return
	 */
	public String getPids() {
		if (getProcessIds().size() > 0)
			return "view";

		return null;
	}

	/**
	 * The string that is returned is used to compute the URL to the actual processes
	 * 
	 * @return
	 */
	public String getPidUrl() {
		String pids = "";

		/* The URL contains a list of comma-separated process ids. Ugly, I know. */
		for (Long id : getProcessIds()) {
			if (pids.length() > 0)
				pids += ",";

			pids += id.toString();
		}

		return pids;
	}

	/**
	 * Returns the list of unique process ids that have sent progress items for this title
	 * 
	 * @return
	 */
	private Collection<Long> getProcessIds() {
		Collection<Long> ids = new HashSet<Long>();
		for (ProgressItem progress : this.progressItems) {
			Long id = this.getProcessId(progress);
			if (id != null) {
				ids.add(id);
			}
		}
		return ids;
	}
	
	private Long getProcessId(ProgressItem progress) {
		// only workflow progress items have a processid.
		if (progress.getSourceEntityName() != null
				&& progress.getSourceEntityName().contains("Workflow")) {
			// NOTE: The sourceId sent by the workflow component is of the
			// form 'processId|tokenId'
			StringTokenizer tokenizer = new StringTokenizer(progress
					.getSourceId().trim(), "|");
			if (tokenizer.countTokens() > 1) {
				Long id = Long.parseLong(tokenizer.nextToken());
				return id;
			}
		}
		return null;
	}

	/**
	 * Returns the value of the parameter of the specified name.
	 * 
	 * @param parameter
	 * @return
	 * 
	 * @see #getParameter(String)
	 */
	/* This method is required for Export To Excel functionality */
	public String getParamValue(String parameter) {
		return getParameter(parameter, null);
	}
	
	/**
	 * Returns the value of the parameter of the specified name
	 * 
	 * @param name
	 * @return
	 */
	public String getParameter(String parameter, String sectionName) {
		if (getIsMetadata(parameter))
			return super.getTitleMetadata(parameter, sectionName);

		/* Progress item needs some parsing... */
		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name);

		if (progress == null)
			return "";

		/* Return success or failure */
		if (progress.getIsSuccess())
			return "OK";

		return "X";
	}

	/**
	 * Returns the value of the parameter of the specified name for the given index. This is used
	 * only for displaying a column value that is a progress item
	 * 
	 * @param parameter
	 * @param index
	 * @return
	 */
	public String getParameter(String parameter, int index) {
		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name, index);

		if (progress == null)
			return "&nbsp;";

		/* Return success or failure */
		if (progress.getIsSuccess())
			return "OK";

		return "X";
	}

	/**
	 * Returns the URL for creating the hyperlink for an entry
	 * 
	 * @param parameter
	 * @return
	 */
	public String getUrlValue(String parameter) {
		if (getIsMetadata(parameter))
			return null;

		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name);

		if (progress != null) {
			Long id = getProcessId(progress);

			if (id != null)
				return id.toString();
		}
		return null;
	}

	/**
	 * Returns the URL for creating the hyperlink for an entry. The index corresponds to the actual
	 * progress we're interested in.
	 * 
	 * @param parameter
	 * @return
	 */
	public String getUrlValue(String parameter, int index) {
		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name, index);

		if (progress != null) {
			Long id = getProcessId(progress);

			if (id != null)
				return id.toString();
		}
		return null;
	}

	/**
	 * Returns the title attribute of a hyperlink
	 * 
	 * @param parameter
	 * @return
	 */
	public String getHoverText(String parameter) {
		if (getIsMetadata(parameter))
			return "";

		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name);

		if (progress != null)
			return CommonUtils.formatTime(progress.getTimestamp());

		return "";
	}

	/**
	 * Returns the title attribute of a hyperlink
	 * 
	 * @param parameter
	 * @return
	 */
	public String getHoverText(String parameter, int index) {
		String name = parameter.substring(PROGRESS.length());
		ProgressItem progress = getProgressItem(name, index);

		if (progress != null)
			return CommonUtils.formatTime(progress.getTimestamp());

		return "";
	}

	private ProgressItem getProgressItem(String name) {
		for (ProgressItem progress : progressItems) {
			if (progress.getName().equalsIgnoreCase(name))
				return progress;
		}

		return null;
	}

	/**
	 * Returns the progress item of the pitch schedule at the specified index
	 * 
	 * @param name
	 * @param index
	 * @return
	 */
	private ProgressItem getProgressItem(String name, int index) {
		int i = 0;

		for (ScheduleData data : this.destinations) {
			if (i == index) {
				for (ProgressItem progress : data.getProgressItems()) {
					if (name.equalsIgnoreCase(progress.getName()))
						return progress;
				}
			}

			i++;
		}

		return null;
	}

	public int compareTo(TitleProgressBean titleProgress) {
		int lastCmp = titleProgress.getId().compareTo(this.getId());
		return lastCmp;
	}
}
