/*
 * Copyright (c) 2011, Patrik Dufresne. All rights reserved.
 * Patrik Dufresne PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.planimod.ui.views.planif.printing;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import com.patrikdufresne.util.DateFormatRegistry;
import com.patrikdufresne.util.Localized;
import com.planimod.core.Employee;
import com.planimod.core.NonAvailability;
import com.planimod.core.Position;
import com.planimod.core.Product;
import com.planimod.core.Shift;
import com.planimod.core.Task;
import com.planimod.core.TimeRange;
import com.planimod.core.TimeRanges;
import com.planimod.core.comparators.TimeRangeComparators;
import com.planimod.ui.printing.PlanimodPrintUtil;
import com.planimod.ui.viewers.EmployeeViewerUtils;

public class PlanifSummaryHelper {

	/**
	 * Used for localization.
	 */
	static Localized localized = Localized.load(PlanifSummaryHelper.class);

	/**
	 * Return a string representation of the production information with the
	 * number of required employee.
	 * 
	 * @param production
	 * @param count
	 * @return
	 */
	public static String getProduction(Product product, Integer count) {
		String family = product.getFamily() == null
				|| product.getFamily().isEmpty() ? null : product.getFamily();
		String name = product.getName() == null || product.getName().isEmpty() ? null
				: product.getName();
		String refId = product.getRefId() == null
				|| product.getRefId().isEmpty() ? null : product.getRefId();
		String format = "%s %d"; //$NON-NLS-1$
		if (family != null) {
			return String.format(format, family, count);
		} else if (name != null) {
			return String.format(format, name, count);
		} else if (refId != null) {
			return String.format(format, refId, count);
		}
		// TODO Localize this string.
		return String.format(format, "unknown", count); //$NON-NLS-1$
	}

	/**
	 * Format the employee name as follow. <count> <employee's name>
	 * [<classified symbol>] [<swappable symbol>]
	 * 
	 * @param count
	 *            the employee count
	 * @param e
	 *            the employee
	 * @param classified
	 *            True if assigned to classified position
	 * @param swappable
	 *            True if the employee is assign to a swappable
	 * @return
	 */
	public static String getEmployeeName(int count, Employee e,
			boolean classified, boolean swappable) {

		StringBuffer buf = new StringBuffer();
		buf.append(count);
		buf.append(PlanimodPrintUtil.SPACE);
		buf.append(EmployeeViewerUtils.getName(e));
		if (classified) {
			buf.append(localized
					.get("PlanifSummaryPrintFactory.classifiedSymbol")); //$NON-NLS-1$
		}
		if (swappable) {
			buf.append(localized
					.get("PlanifSummaryPrintFactory.swappableSymbol")); //$NON-NLS-1$
		}

		return buf.toString();

	}

	/**
	 * Return a string representation of the non availability.
	 * 
	 * @param range
	 *            the current time range displayed.
	 * @param na
	 *            the non-availability
	 * @return the string representation of the non-availability
	 */
	public static String getNonAvailabilityDesc(TimeRange range,
			NonAvailability na) {

		StringBuilder buf = new StringBuilder();
		buf.append(PlanimodPrintUtil.getName(na.getEmployee()));
		buf.append(" - "); //$NON-NLS-1$
		if (na.getSummary() != null) {
			buf.append(na.getSummary());
		}
		return buf.toString();

	}

	/**
	 * Return a string representation of the non-availability.
	 * 
	 * @param na
	 *            the non-availability.
	 * @param tasks
	 *            all tasks in the team.
	 * @return
	 */
	public static String getNonAvailabilityDesc(NonAvailability na,
			Collection<Shift> shifts) {

		List<Shift> orderShifts = new ArrayList<Shift>(shifts);
		Collections.sort(orderShifts, TimeRangeComparators.byDate());

		StringBuilder buf = new StringBuilder();
		buf.append(PlanimodPrintUtil.getName(na.getEmployee()));
		buf.append(" - "); //$NON-NLS-1$
		if (na.getSummary() != null) {
			buf.append(na.getSummary());
		}
		buf.append(" ("); //$NON-NLS-1$

		int count = 0;
		for (int i = 0; i < orderShifts.size(); i++) {

			Shift s = orderShifts.get(i);
			if (TimeRanges.containsEquals(na, s)) {
				buf.append(count > 0 ? " " : ""); //$NON-NLS-1$ //$NON-NLS-2$
				buf.append(DateFormatRegistry.format(s.getStartDate(),
						DateFormatRegistry.DAY_OF_WEEK));
				count++;
			} else if (TimeRanges.intersectBefore(na, s)) {
				buf.append(count > 0 ? " " : ""); //$NON-NLS-1$ //$NON-NLS-2$
				buf.append(DateFormatRegistry.format(s.getStartDate(),
						DateFormatRegistry.DAY_OF_WEEK));
				buf.append(" - ");
				buf.append(DateFormatRegistry.format(s.getStartDate(),
						DateFormatRegistry.TIME | DateFormatRegistry.MEDIUM));
				count++;
			} else if (TimeRanges.intersectAfter(na, s)) {
				buf.append(count > 0 ? " " : ""); //$NON-NLS-1$ //$NON-NLS-2$
				buf.append(DateFormatRegistry.format(s.getStartDate(),
						DateFormatRegistry.TIME | DateFormatRegistry.MEDIUM));
				buf.append(" - ..");
				count++;
			} else if (TimeRanges.containsEquals(s, na)) {
				buf.append(count > 0 ? " " : ""); //$NON-NLS-1$ //$NON-NLS-2$
				buf.append(DateFormatRegistry.formatRange(na.getStartDate(),
						na.getEndDate(), DateFormatRegistry.TIME
								| DateFormatRegistry.MEDIUM));
				count++;
			}

		}
		buf.append(")");

		return buf.toString();
	}

	/**
	 * Return a string representation of the vacant tasks.
	 * <p>
	 * The received collection should correspond to the same task with different
	 * day for the same team. If the collection doesn't represent the same task,
	 * this function return an unexpected value.
	 * 
	 * @param tasks
	 *            collection of tasks representing a position within one team
	 *            being vacant.
	 * 
	 * @return the description of the task being vacant. e.g.: <Position name> -
	 *         <days>
	 */
	public static String getVacantDesc(Collection<Task> tasks) {
		if (tasks.size() == 0) {
			throw new IllegalArgumentException();
		}

		Position position = tasks.iterator().next().getPosition();
		if (position == null) {
			return ""; //$NON-NLS-1$
		}

		/*
		 * Build list of days
		 */
		Collection<Integer> days = new HashSet<Integer>();
		Calendar cal = Calendar.getInstance();
		for (Task task : tasks) {
			cal.setTime(task.getStartDate());
			days.add(Integer.valueOf(cal.get(Calendar.DAY_OF_WEEK)));
		}
		days = new ArrayList<Integer>(days);
		Collections.sort((List<Integer>) days);

		/*
		 * Build the string.
		 */
		StringBuilder buf = new StringBuilder();
		buf.append(PlanimodPrintUtil.getName(position));
		buf.append(" ("); //$NON-NLS-1$

		int count = 0;
		SimpleDateFormat dateformat = new SimpleDateFormat("EE");
		for (Integer day : days) {
			cal.set(Calendar.DAY_OF_WEEK, day.intValue());
			buf.append(count > 0 ? " " : ""); //$NON-NLS-1$ //$NON-NLS-2$
			buf.append(dateformat.format(cal.getTime()));
			count++;
		}
		buf.append(")"); //$NON-NLS-1$

		return buf.toString();
	}

	/**
	 * Return a string to identify a recall from non-availability
	 * 
	 * @return
	 */
	public static String recall() {
		return localized.get("PlanifSummaryHelper.recallFromNonAvailability"); //$NON-NLS-1$
	}

}
