/*******************************************************************************
 * Copyright (c) 2004 - 2006 University Of British Columbia and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University Of British Columbia - initial API and implementation
 *******************************************************************************/
/*
 * Created on Dec 26, 2004
 */
package org.eclipse.mylar.tasks.ui;

import java.io.File;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.mylar.context.core.ContextCorePlugin;
import org.eclipse.mylar.context.core.IMylarContext;
import org.eclipse.mylar.context.core.IMylarContextListener;
import org.eclipse.mylar.context.core.IMylarElement;
import org.eclipse.mylar.core.MylarStatusHandler;
import org.eclipse.mylar.internal.context.core.MylarContextManager;
import org.eclipse.mylar.internal.tasks.core.RepositoryTaskHandleUtil;
import org.eclipse.mylar.internal.tasks.core.WebTask;
import org.eclipse.mylar.internal.tasks.ui.TaskListPreferenceConstants;
import org.eclipse.mylar.internal.tasks.ui.WorkspaceAwareContextStore;
import org.eclipse.mylar.internal.tasks.ui.util.TaskListSaveManager;
import org.eclipse.mylar.internal.tasks.ui.util.TaskListWriter;
import org.eclipse.mylar.internal.tasks.ui.views.TaskActivationHistory;
import org.eclipse.mylar.monitor.core.InteractionEvent;
import org.eclipse.mylar.tasks.core.AbstractQueryHit;
import org.eclipse.mylar.tasks.core.AbstractRepositoryTask;
import org.eclipse.mylar.tasks.core.AbstractTaskContainer;
import org.eclipse.mylar.tasks.core.DateRangeActivityDelegate;
import org.eclipse.mylar.tasks.core.DateRangeContainer;
import org.eclipse.mylar.tasks.core.ITask;
import org.eclipse.mylar.tasks.core.ITaskActivityListener;
import org.eclipse.mylar.tasks.core.ITaskListChangeListener;
import org.eclipse.mylar.tasks.core.ITaskListElement;
import org.eclipse.mylar.tasks.core.TaskList;
import org.eclipse.mylar.tasks.core.TaskRepository;
import org.eclipse.mylar.tasks.core.TaskRepositoryManager;

/**
 * TODO: pull task activity management out into new TaskActivityManager
 * 
 * @author Mik Kersten
 * @author Rob Elves (task activity)
 */
public class TaskListManager implements IPropertyChangeListener {

	// Did have preference for this so should re-enable
	private static final int START_HOUR = 8;

	private static final long SECOND = 1000;

	private static final long MINUTE = 60 * SECOND;

	private static final long ROLLOVER_DELAY = 30 * MINUTE;

	private static final int NUM_WEEKS_PREVIOUS = -1;

	private static final int NUM_WEEKS_NEXT = 1;

	private static final int NUM_WEEKS_FUTURE_START = 2;

	private static final int NUM_WEEKS_FUTURE_END = 8;

	private static final int NUM_WEEKS_PAST_START = -8;

	private static final int NUM_WEEKS_PAST_END = -2;

	public static final String ARCHIVE_CATEGORY_DESCRIPTION = "Archive";

	private static final String DESCRIPTION_THIS_WEEK = "This Week";

	private static final String DESCRIPTION_PREVIOUS_WEEK = "Previous Week";

	private static final String DESCRIPTION_NEXT_WEEK = "Next Week";

	private static final String DESCRIPTION_FUTURE = "Future";

	private static final String DESCRIPTION_PAST = "Past";

	public static final String[] ESTIMATE_TIMES = new String[] { "0 Hours", "1 Hours", "2 Hours", "3 Hours", "4 Hours",
			"5 Hours", "6 Hours", "7 Hours", "8 Hours", "9 Hours", "10 Hours" };

	private DateRangeContainer activityPreviousWeek;

	private DateRangeContainer activityThisWeek;

	private List<DateRangeContainer> activityWeekDays = new ArrayList<DateRangeContainer>();

	private DateRangeContainer activityNextWeek;

	private DateRangeContainer activityFuture;

	private DateRangeContainer activityPast;

	private ArrayList<DateRangeContainer> dateRangeContainers = new ArrayList<DateRangeContainer>();

	private Set<ITask> tasksWithReminders = new HashSet<ITask>();

	private Set<ITask> tasksWithDueDates = new HashSet<ITask>();

	private ITask currentTask = null;

	private String currentHandle = "";

	private Calendar currentTaskStart = null;

	private Calendar currentTaskEnd = null;

	private Map<ITask, Long> taskElapsedTimeMap = new ConcurrentHashMap<ITask, Long>();

	private List<ITaskActivityListener> activityListeners = new ArrayList<ITaskActivityListener>();

	private TaskListWriter taskListWriter;

	private File taskListFile;

	private TaskListSaveManager taskListSaveManager;

	// TODO: guard against overwriting the single instance?
	private TaskList taskList = new TaskList();

	private TaskActivationHistory taskActivityHistory = new TaskActivationHistory();

	private boolean taskListInitialized = false;

	private boolean taskActivityHistoryInitialized = false;

	private int startDay;

	private int endDay;

	private int scheduledEndHour;

	private Timer timer;

	/** public for testing */
	public Date startTime = new Date();

	private final IMylarContextListener CONTEXT_LISTENER = new IMylarContextListener() {

		public void contextActivated(IMylarContext context) {
			// ignore
		}

		public void contextDeactivated(IMylarContext context) {
			// ignore
		}

		public void presentationSettingsChanging(UpdateKind kind) {
			// ignore
		}

		public void presentationSettingsChanged(UpdateKind kind) {
			// ignore
		}

		public void interestChanged(List<IMylarElement> elements) {
			List<InteractionEvent> events = ContextCorePlugin.getContextManager().getActivityHistoryMetaContext()
					.getInteractionHistory();
			InteractionEvent event = events.get(events.size() - 1);
			parseInteractionEvent(event);

		}

		public void elementDeleted(IMylarElement element) {
			// ignore
		}

		public void landmarkAdded(IMylarElement element) {
			// ignore
		}

		public void landmarkRemoved(IMylarElement element) {
			// ignore
		}

		public void relationsChanged(IMylarElement element) {
			// ignore
		}
	};

	private final ITaskListChangeListener CHANGE_LISTENER = new ITaskListChangeListener() {

		public void containerAdded(AbstractTaskContainer container) {
		}

		public void containerDeleted(AbstractTaskContainer container) {
		}

		public void containerInfoChanged(AbstractTaskContainer container) {
		}

		public void localInfoChanged(ITask task) {
		}

		public void repositoryInfoChanged(ITask task) {
		}

		public void taskAdded(ITask task) {
		}

		public void taskDeleted(ITask task) {
			TaskListManager.this.resetAndRollOver();
		}

		public void taskMoved(ITask task, AbstractTaskContainer fromContainer, AbstractTaskContainer toContainer) {
		}

	};

	private int timeTicks = 0;

	public TaskListManager(TaskListWriter taskListWriter, File file) {
		this.taskListFile = file;
		this.taskListWriter = taskListWriter;

		timer = new Timer();
		timer.schedule(new RolloverCheck(), ROLLOVER_DELAY, ROLLOVER_DELAY);
		taskList.addChangeListener(CHANGE_LISTENER);
	}

	public void init() {
		ContextCorePlugin.getContextManager().addActivityMetaContextListener(CONTEXT_LISTENER);
	}

	public void dispose() {
		ContextCorePlugin.getContextManager().removeActivityMetaContextListener(CONTEXT_LISTENER);
	}

	public TaskList resetTaskList() {
		resetActivity();
		taskList.reset();
		taskListInitialized = true;
		return taskList;
	}

	private void resetActivity() {
		taskElapsedTimeMap.clear();
		dateRangeContainers.clear();
		setupCalendarRanges();
	}

	/**
	 * Warning: if called twice task times will be wrong
	 */
	private void parseTaskActivityInteractionHistory() {
		if (!TasksUiPlugin.getTaskListManager().isTaskListInitialized()) {
			return;
		}
		List<InteractionEvent> events = ContextCorePlugin.getContextManager().getActivityHistoryMetaContext()
				.getInteractionHistory();
		for (InteractionEvent event : events) {
			try {
				parseInteractionEvent(event);
			} catch (Exception e) {
				MylarStatusHandler.fail(e, "Error parsing interaction event", false);
			}
		}
		taskActivityHistoryInitialized = true;
		parseFutureReminders();
	}

	public void parseFutureReminders() {
		activityFuture.clear();
		activityNextWeek.clear();

		for (DateRangeContainer day : activityWeekDays) {
			day.clear();
		}
		HashSet<ITask> toRemove = new HashSet<ITask>();
		toRemove.addAll(activityThisWeek.getDateRangeDelegates());
		for (ITask activity : toRemove) {
			DateRangeActivityDelegate delegate = (DateRangeActivityDelegate) activity;
			Calendar calendar = GregorianCalendar.getInstance();

			Date schedDate = delegate.getScheduledForDate();
			if (schedDate == null) {
				schedDate = delegate.getDueDate();
			}

			if (schedDate != null) {
				calendar.setTime(schedDate);
				if (!activityThisWeek.includes(calendar) && activityThisWeek.getElapsed(delegate) == 0) {
					activityThisWeek.remove(delegate);
				}
			} else {
				if (activityThisWeek.getElapsed(delegate) == 0) {
					activityThisWeek.remove(delegate);
				}
			}
		}
		GregorianCalendar tempCalendar = new GregorianCalendar();
		tempCalendar.setFirstDayOfWeek(startDay);

		Set<ITask> allScheduledTasks = new HashSet<ITask>();
		allScheduledTasks.addAll(tasksWithReminders);
		allScheduledTasks.addAll(tasksWithDueDates);

		for (ITask task : allScheduledTasks) {
			if (task instanceof DateRangeActivityDelegate) {
				task = ((DateRangeActivityDelegate) task).getCorrespondingTask();
			}

			Date schedDate = task.getScheduledForDate();
			if (schedDate == null || isOverdue(task)) {
				schedDate = task.getDueDate();
			}

			if (schedDate != null) {
				tempCalendar.setTime(schedDate);
				if (activityNextWeek.includes(tempCalendar)) {
					activityNextWeek.addTask(new DateRangeActivityDelegate(activityNextWeek, task, tempCalendar,
							tempCalendar));
				} else if (activityFuture.includes(tempCalendar)) {
					activityFuture.addTask(new DateRangeActivityDelegate(activityFuture, task, tempCalendar,
							tempCalendar));
				} else if (activityThisWeek.includes(tempCalendar) && !activityThisWeek.getChildren().contains(task)) {
					activityThisWeek.addTask(new DateRangeActivityDelegate(activityThisWeek, task, tempCalendar,
							tempCalendar));
				} else if (activityPreviousWeek.includes(tempCalendar)
						&& !activityPreviousWeek.getChildren().contains(task)) {
					activityPreviousWeek.addTask(new DateRangeActivityDelegate(activityPreviousWeek, task,
							tempCalendar, tempCalendar));
				} else if (activityPast.includes(tempCalendar) && !activityPast.getChildren().contains(task)) {
					activityPast.addTask(new DateRangeActivityDelegate(activityPast, task, tempCalendar, tempCalendar));
				}

				for (DateRangeContainer day : activityWeekDays) {
					if (day.includes(tempCalendar) && !day.getChildren().contains(task)) {
						day.addTask(new DateRangeActivityDelegate(day, task, tempCalendar, tempCalendar, this
								.getElapsedTime(task)));
					}
				}
			}
		}
	}

	/** public for testing * */
	public void parseInteractionEvent(InteractionEvent event) {

		if (event.getDelta().equals(MylarContextManager.ACTIVITY_DELTA_ACTIVATED)) {
			if (!event.getStructureHandle().equals(MylarContextManager.ACTIVITY_HANDLE_ATTENTION)) {

				ITask activatedTask = TasksUiPlugin.getTaskListManager().getTaskList().getTask(
						event.getStructureHandle());

				if (currentTask != null && activatedTask != null) {
					if (!currentTask.equals(activatedTask)) {

						GregorianCalendar calendarEnd = new GregorianCalendar();
						calendarEnd.setFirstDayOfWeek(startDay);
						calendarEnd.setTime(event.getDate());
						calendarEnd.getTime();
						// Activation of different task before deactivation of
						// previous, log was inconsistent,
						// finish what we started
						taskDeactivated(calendarEnd);
					} else {
						// skip re-activations of same task
						return;
					}
				}

				currentTask = activatedTask;
				if (currentTask != null) {
					GregorianCalendar calendar = new GregorianCalendar();
					calendar.setFirstDayOfWeek(startDay);
					calendar.setTime(event.getDate());
					currentTaskStart = calendar;
					currentHandle = event.getStructureHandle();
				}
			} else if (event.getStructureHandle().equals(MylarContextManager.ACTIVITY_HANDLE_ATTENTION)) {
				if (currentTask != null && !currentHandle.equals("")) {
					long active = event.getEndDate().getTime() - event.getDate().getTime();

					// add to running total
					if (taskElapsedTimeMap.containsKey(currentTask)) {
						long pastTime = taskElapsedTimeMap.get(currentTask);
						taskElapsedTimeMap.put(currentTask, pastTime + active);
						timeTicks++;
						if (taskActivityHistoryInitialized && timeTicks > 3) {
							// Save incase of system failure.
							// TODO: request asynchronous save
							ContextCorePlugin.getContextManager().saveActivityHistoryContext();
							timeTicks = 0;
						}

					} else {
						taskElapsedTimeMap.put(currentTask, active);
					}
				}
			}
		} else if (event.getDelta().equals(MylarContextManager.ACTIVITY_DELTA_DEACTIVATED)) {
			if (!event.getStructureHandle().equals(MylarContextManager.ACTIVITY_HANDLE_ATTENTION)
					&& currentHandle.equals(event.getStructureHandle())) {
				GregorianCalendar calendarEnd = new GregorianCalendar();
				calendarEnd.setFirstDayOfWeek(startDay);
				calendarEnd.setTime(event.getDate());
				calendarEnd.getTime();
				taskDeactivated(calendarEnd);
			} else if (event.getStructureHandle().equals(MylarContextManager.ACTIVITY_HANDLE_ATTENTION)) {
				// Deactivated attention events not currently used (ignored)
			}
		}
	}

	private void taskDeactivated(GregorianCalendar calendarEnd) {
		currentTaskEnd = calendarEnd;

		Set<DateRangeContainer> rangeSet = new HashSet<DateRangeContainer>();
		rangeSet.addAll(dateRangeContainers);
		rangeSet.add(activityThisWeek);

		for (DateRangeContainer week : rangeSet) {
			if (week.includes(currentTaskStart) && (!isWeekDay(week) && !week.isFuture())) {
				if (currentTask != null) {
					// add to date range 'bin'
					Long activeTime = taskElapsedTimeMap.get(currentTask);
					if (activeTime == null) {
						activeTime = new Long(0);
					}
					DateRangeActivityDelegate delegate = new DateRangeActivityDelegate(week, currentTask,
							currentTaskStart, currentTaskEnd, activeTime);
					week.addTask(delegate);
					if (taskActivityHistoryInitialized) {
						for (ITaskActivityListener listener : activityListeners) {
							listener.activityChanged(week);
						}
					}
				}
			}
		}

		currentTask = null;
		currentHandle = "";
	}

	/** public for testing * */
	public DateRangeContainer getActivityThisWeek() {
		return activityThisWeek;
	}

	/** public for testing * */
	public DateRangeContainer getActivityPast() {
		return activityPast;
	}

	/** public for testing * */
	public DateRangeContainer getActivityFuture() {
		return activityFuture;
	}

	/** public for testing * */
	public DateRangeContainer getActivityNextWeek() {
		return activityNextWeek;
	}

	/** public for testing * */
	public DateRangeContainer getActivityPrevious() {
		return activityPreviousWeek;
	}

	/** total elapsed time based on activation history */
	public long getElapsedTime(ITask task) {
		if (taskElapsedTimeMap.containsKey(task)) {
			return taskElapsedTimeMap.get(task);
		} else {
			return 0;
		}
	}

	private void setupCalendarRanges() {
		// MylarTaskListPlugin.getMylarCorePrefs().getInt(TaskListPreferenceConstants.PLANNING_STARTDAY);
		startDay = Calendar.MONDAY;
		// MylarTaskListPlugin.getMylarCorePrefs().getInt(TaskListPreferenceConstants.PLANNING_ENDDAY);
		endDay = Calendar.SUNDAY;
		// scheduledStartHour =
		// TasksUiPlugin.getDefault().getPreferenceStore().getInt(
		// TaskListPreferenceConstants.PLANNING_STARTHOUR);
		scheduledEndHour = TasksUiPlugin.getDefault().getPreferenceStore().getInt(
				TaskListPreferenceConstants.PLANNING_ENDHOUR);

		activityWeekDays.clear();
		for (int x = startDay; x < (startDay + 7); x++) {
			GregorianCalendar dayStart = new GregorianCalendar();
			GregorianCalendar dayEnd = new GregorianCalendar();
			dayStart.setFirstDayOfWeek(startDay);
			dayEnd.setFirstDayOfWeek(startDay);
			if (x > 7) {
				dayStart.set(Calendar.DAY_OF_WEEK, x % 7);
				dayEnd.set(Calendar.DAY_OF_WEEK, x % 7);
			} else {
				dayStart.set(Calendar.DAY_OF_WEEK, x);
				dayEnd.set(Calendar.DAY_OF_WEEK, x);
			}

			dayStart.set(Calendar.HOUR_OF_DAY, 0);
			dayStart.set(Calendar.MINUTE, 0);
			dayStart.set(Calendar.SECOND, 0);
			dayStart.set(Calendar.MILLISECOND, 0);
			dayStart.getTime();

			dayEnd.set(Calendar.HOUR_OF_DAY, dayEnd.getMaximum(Calendar.HOUR_OF_DAY));
			dayEnd.set(Calendar.MINUTE, dayEnd.getMaximum(Calendar.MINUTE));
			dayEnd.set(Calendar.SECOND, dayEnd.getMaximum(Calendar.SECOND));
			dayEnd.set(Calendar.MILLISECOND, dayEnd.getMaximum(Calendar.MILLISECOND));
			dayEnd.getTime();

			String summary = "<unknown>";
			switch (dayStart.get(Calendar.DAY_OF_WEEK)) {
			case Calendar.MONDAY:
				summary = "Monday";
				break;
			case Calendar.TUESDAY:
				summary = "Tuesday";
				break;
			case Calendar.WEDNESDAY:
				summary = "Wednesday";
				break;
			case Calendar.THURSDAY:
				summary = "Thursday";
				break;
			case Calendar.FRIDAY:
				summary = "Friday";
				break;
			case Calendar.SATURDAY:
				summary = "Saturday";
				break;
			case Calendar.SUNDAY:
				summary = "Sunday";
				break;
			}
			DateRangeContainer day = new DateRangeContainer(dayStart, dayEnd, summary, taskList);
			activityWeekDays.add(day);
			dateRangeContainers.add(day);
		}

		GregorianCalendar currentBegin = new GregorianCalendar();
		currentBegin.setFirstDayOfWeek(startDay);
		currentBegin.setTime(startTime);
		snapToStartOfWeek(currentBegin);
		GregorianCalendar currentEnd = new GregorianCalendar();
		currentEnd.setFirstDayOfWeek(startDay);
		currentEnd.setTime(startTime);
		snapToEndOfWeek(currentEnd);
		activityThisWeek = new DateRangeContainer(currentBegin, currentEnd, DESCRIPTION_THIS_WEEK, taskList);
		// dateRangeContainers.add(activityThisWeek);

		GregorianCalendar previousStart = new GregorianCalendar();
		previousStart.setFirstDayOfWeek(startDay);
		previousStart.setTime(startTime);
		previousStart.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_PREVIOUS);
		snapToStartOfWeek(previousStart);
		GregorianCalendar previousEnd = new GregorianCalendar();
		previousEnd.setFirstDayOfWeek(startDay);
		previousEnd.setTime(startTime);
		previousEnd.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_PREVIOUS);
		snapToEndOfWeek(previousEnd);
		activityPreviousWeek = new DateRangeContainer(previousStart.getTime(), previousEnd.getTime(),
				DESCRIPTION_PREVIOUS_WEEK, taskList);
		dateRangeContainers.add(activityPreviousWeek);

		GregorianCalendar nextStart = new GregorianCalendar();
		nextStart.setFirstDayOfWeek(startDay);
		nextStart.setTime(startTime);
		nextStart.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_NEXT);
		snapToStartOfWeek(nextStart);
		GregorianCalendar nextEnd = new GregorianCalendar();
		nextEnd.setFirstDayOfWeek(startDay);
		nextEnd.setTime(startTime);
		nextEnd.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_NEXT);
		snapToEndOfWeek(nextEnd);
		activityNextWeek = new DateRangeContainer(nextStart.getTime(), nextEnd.getTime(), DESCRIPTION_NEXT_WEEK,
				taskList);
		dateRangeContainers.add(activityNextWeek);

		GregorianCalendar futureStart = new GregorianCalendar();
		futureStart.setFirstDayOfWeek(startDay);
		futureStart.setTime(startTime);
		futureStart.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_FUTURE_START);
		snapToStartOfWeek(futureStart);
		GregorianCalendar futureEnd = new GregorianCalendar();
		futureEnd.setFirstDayOfWeek(startDay);
		futureEnd.setTime(startTime);
		futureEnd.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_FUTURE_END);
		snapToEndOfWeek(futureEnd);
		activityFuture = new DateRangeContainer(futureStart.getTime(), futureEnd.getTime(), DESCRIPTION_FUTURE,
				taskList);
		dateRangeContainers.add(activityFuture);

		GregorianCalendar pastStart = new GregorianCalendar();
		pastStart.setFirstDayOfWeek(startDay);
		pastStart.setTime(startTime);
		pastStart.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_PAST_START);
		snapToStartOfWeek(pastStart);
		GregorianCalendar pastEnd = new GregorianCalendar();
		pastEnd.setFirstDayOfWeek(startDay);
		pastEnd.setTime(startTime);
		pastEnd.add(Calendar.WEEK_OF_YEAR, NUM_WEEKS_PAST_END);
		snapToEndOfWeek(pastEnd);
		activityPast = new DateRangeContainer(pastStart.getTime(), pastEnd.getTime(), DESCRIPTION_PAST, taskList);
		dateRangeContainers.add(activityPast);
	}

	public void snapToNextDay(Calendar cal) {
		cal.add(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.getTime();
	}

	private void snapToStartOfWeek(Calendar cal) {
		cal.getTime();
		cal.set(Calendar.DAY_OF_WEEK, startDay);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.getTime();
	}

	private void snapToEndOfWeek(Calendar cal) {
		cal.getTime();
		cal.set(Calendar.DAY_OF_WEEK, endDay);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
		cal.getTime();
	}

	public Calendar setSecheduledIn(Calendar calendar, int days) {
		calendar.add(Calendar.DAY_OF_MONTH, days);
		calendar.set(Calendar.HOUR_OF_DAY, scheduledEndHour);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar;
	}

	/**
	 * Will schedule for today if past work-day's end.
	 */
	public Calendar setScheduledEndOfDay(Calendar calendar) {
		// Calendar now = Calendar.getInstance();
		// if (now.get(Calendar.HOUR_OF_DAY) >= scheduledEndHour) {
		// setSecheduledIn(calendar, 1);
		// }
		calendar.set(Calendar.HOUR_OF_DAY, scheduledEndHour);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar;
	}

	public void setScheduledNextWeek(Calendar calendar) {
		calendar.setTimeInMillis(TasksUiPlugin.getTaskListManager().getActivityNextWeek().getStart().getTimeInMillis());
		setScheduledEndOfDay(calendar);
	}

	public List<DateRangeContainer> getDateRanges() {
		// parseFutureReminders();
		// return dateRangeContainers.toArray(new
		// ITaskListElement[dateRangeContainers.size()]);
		return dateRangeContainers;
	}

	/**
	 * Every call to this method generates a unique handle, subsequent calls
	 * will have incremented task numbers
	 */
	public String genUniqueTaskHandle() {
		return TaskRepositoryManager.PREFIX_LOCAL + taskList.getNextTaskNum();
	}

	public void refactorRepositoryUrl(String oldUrl, String newUrl) {
		if (oldUrl == null || newUrl == null || oldUrl.equals(newUrl)) {
			return;
		}
		List<ITask> activeTasks = taskList.getActiveTasks();
		for (ITask task : new ArrayList<ITask>(activeTasks)) {
			deactivateTask(task);
		}
		taskList.refactorRepositoryUrl(oldUrl, newUrl);

		File dataDir = new File(TasksUiPlugin.getDefault().getDataDirectory(),
				WorkspaceAwareContextStore.CONTEXTS_DIRECTORY);
		if (dataDir.exists() && dataDir.isDirectory()) {
			for (File file : dataDir.listFiles()) {
				int dotIndex = file.getName().lastIndexOf(".xml");
				if (dotIndex != -1) {
					String storedHandle;
					try {
						storedHandle = URLDecoder.decode(file.getName().substring(0, dotIndex),
								MylarContextManager.CONTEXT_FILENAME_ENCODING);
						int delimIndex = storedHandle.lastIndexOf(RepositoryTaskHandleUtil.HANDLE_DELIM);
						if (delimIndex != -1) {
							String storedUrl = storedHandle.substring(0, delimIndex);
							if (oldUrl.equals(storedUrl)) {
								String id = RepositoryTaskHandleUtil.getTaskId(storedHandle);
								String newHandle = RepositoryTaskHandleUtil.getHandle(newUrl, id);
								File newFile = ContextCorePlugin.getContextManager().getFileForContext(newHandle);
								file.renameTo(newFile);
							}
						}
					} catch (Exception e) {
						MylarStatusHandler.fail(e, "Could not move context file: " + file.getName(), false);
					}
				}
			}
		}
		saveTaskList();
	}

	public boolean readExistingOrCreateNewList() {
		try {
			if (taskListFile.exists()) {
				taskListWriter.readTaskList(taskList, taskListFile, TasksUiPlugin.getDefault().getTaskDataManager());
			} else {
				resetTaskList();
			}

			for (ITask task : taskList.getAllTasks()) {
				if (task.getScheduledForDate() != null) {
					tasksWithReminders.add(task);
				}
				if (task.getDueDate() != null) {
					tasksWithDueDates.add(task);
				}
			}

			resetActivity();
			// parseFutureReminders();
			taskListInitialized = true;
			for (ITaskActivityListener listener : new ArrayList<ITaskActivityListener>(activityListeners)) {
				listener.taskListRead();
			}
		} catch (Exception e) {
			MylarStatusHandler.log(e, "Could not read task list");
			return false;
		}
		return true;
	}

	/**
	 * Only to be called upon initial startup by plugin.
	 */
	public void initActivityHistory() {
		resetAndRollOver();
		taskActivityHistory.loadPersistentHistory();
	}

	/**
	 * Will not save an empty task list to avoid losing data on bad startup.
	 */
	public synchronized void saveTaskList() {
		try {
			if (taskListInitialized) {
				taskListSaveManager.saveTaskList(true, false);
				// TasksUiPlugin.getDefault().getPreferenceStore().setValue(TaskListPreferenceConstants.TASK_ID,
				// nextLocalTaskId);
			} else {
				MylarStatusHandler.log("task list save attempted before initialization", this);
			}
		} catch (Exception e) {
			MylarStatusHandler.fail(e, "Could not save task list", true);
		}
	}

	public TaskList getTaskList() {
		return taskList;
	}

	public void addActivityListener(ITaskActivityListener listener) {
		activityListeners.add(listener);
	}

	public void removeActivityListener(ITaskActivityListener listener) {
		activityListeners.remove(listener);
	}

	public void activateTask(ITask task) {
		if (!TasksUiPlugin.getDefault().isMultipleActiveTasksMode()) {
			deactivateAllTasks();
		}

		try {
			taskList.setActive(task, true);
			for (ITaskActivityListener listener : new ArrayList<ITaskActivityListener>(activityListeners)) {
				try {
					listener.taskActivated(task);
				} catch (Throwable t) {
					MylarStatusHandler.fail(t, "task activity listener failed: " + listener, false);
				}
			}
		} catch (Throwable t) {
			MylarStatusHandler.fail(t, "could not activate task", false);
		}
	}

	public void deactivateAllTasks() {
		// Make a copy to avoid modification on list being traversed; can result
		// in a ConcurrentModificationException
		List<ITask> activeTasks = taskList.getActiveTasks();
		for (ITask task : activeTasks) {
			deactivateTask(task);
		}
	}

	public void deactivateTask(ITask task) {
		if (task == null) {
			return;
		}

		if (task.isActive()) {
			taskList.setActive(task, false);
			for (ITaskActivityListener listener : new ArrayList<ITaskActivityListener>(activityListeners)) {
				try {
					listener.taskDeactivated(task);
				} catch (Throwable t) {
					MylarStatusHandler.fail(t, "notification failed for: " + listener, false);
				}
			}
		}
	}

	public void setTaskListFile(File file) {
		this.taskListFile = file;
	}

	public void copyDataDirContentsTo(String newDataDir) {
		taskListSaveManager.copyDataDirContentsTo(newDataDir);
	}

	public boolean isTaskListInitialized() {
		return taskListInitialized;
	}

	public TaskListWriter getTaskListWriter() {
		return taskListWriter;
	}

	public File getTaskListFile() {
		return taskListFile;
	}

	public boolean isActiveThisWeek(ITask task) {
		for (ITask activityDelegateTask : activityThisWeek.getChildren()) {
			if (activityDelegateTask.getHandleIdentifier().equals(task.getHandleIdentifier())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @return if a repository task, will only return true if the user is a
	 */
	public boolean isCompletedToday(ITask task) {
		if (task != null) {

			if (task instanceof AbstractRepositoryTask && !(task instanceof WebTask)) {
				AbstractRepositoryTask repositoryTask = (AbstractRepositoryTask) task;
				TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(
						repositoryTask.getRepositoryKind(), repositoryTask.getRepositoryUrl());

				if (repository != null && repositoryTask.getOwner() != null
						&& !repositoryTask.getOwner().equals(repository.getUserName())) {
					return false;
				}
			}

			Date completionDate = task.getCompletionDate();
			if (completionDate != null) {
				Calendar tomorrow = Calendar.getInstance();
				snapToNextDay(tomorrow);
				Calendar yesterday = Calendar.getInstance();
				yesterday.set(Calendar.HOUR_OF_DAY, 0);
				yesterday.set(Calendar.MINUTE, 0);
				yesterday.set(Calendar.SECOND, 0);
				yesterday.set(Calendar.MILLISECOND, 0);

				return completionDate.compareTo(yesterday.getTime()) == 1
						&& completionDate.compareTo(tomorrow.getTime()) == -1;
			}
		}
		return false;
	}

	public boolean isScheduledAfterThisWeek(ITask task) {
		if (task != null) {
			Date reminder = task.getScheduledForDate();
			if (reminder != null) {
				return reminder.compareTo(activityNextWeek.getStart().getTime()) > -1;
			}
		}
		return false;
	}

	public boolean isScheduledForLater(ITask task) {
		if (task != null) {
			Date reminder = task.getScheduledForDate();
			if (reminder != null) {
				return reminder.compareTo(activityFuture.getStart().getTime()) > -1;
			}
		}
		return false;
	}

	public boolean isScheduledForThisWeek(ITask task) {
		if (task != null) {
			Date reminder = task.getScheduledForDate();
			if (reminder != null) {
				Calendar weekStart = Calendar.getInstance();
				snapToStartOfWeek(weekStart);
				return (reminder.compareTo(weekStart.getTime()) >= 0 && reminder.compareTo(activityThisWeek.getEnd()
						.getTime()) <= 0);
			}
		}
		return false;
	}

	public boolean isScheduledForToday(ITask task) {
		if (task != null) {
			Date reminder = task.getScheduledForDate();
			if (reminder != null) {
				Calendar dayStart = Calendar.getInstance();
				dayStart.set(Calendar.HOUR_OF_DAY, 0);
				dayStart.set(Calendar.MINUTE, 0);
				dayStart.set(Calendar.SECOND, 0);
				dayStart.set(Calendar.MILLISECOND, 0);
				Calendar midnight = GregorianCalendar.getInstance();
				snapToNextDay(midnight);
				return (reminder.compareTo(dayStart.getTime()) >= 0 && reminder.compareTo(midnight.getTime()) == -1);
			}
		}
		return false;
	}

	/**
	 * TODO: Need to migrate to use of this method for setting of reminders
	 */
	public void setScheduledFor(ITask task, Date reminderDate) {
		if (task == null)
			return;
		task.setScheduledForDate(reminderDate);
		task.setReminded(false);
		if (reminderDate == null) {
			tasksWithReminders.remove(task);
		} else {
			tasksWithReminders.remove(task);
			tasksWithReminders.add(task);
		}
		parseFutureReminders();
		taskList.notifyLocalInfoChanged(task);
	}

	public void setDueDate(ITask task, Date dueDate) {
		task.setDueDate(dueDate);
		if (dueDate == null) {
			tasksWithDueDates.remove(task);
		} else {
			tasksWithDueDates.remove(task);
			tasksWithDueDates.add(task);
		}
		parseFutureReminders();
		taskList.notifyLocalInfoChanged(task);
	}

	/**
	 * @return true if task due date != null and has past
	 */
	public boolean isOverdue(ITask task) {
		return (!task.isCompleted() && task.getDueDate() != null && new Date().after(task.getDueDate()));
	}

	public void propertyChange(PropertyChangeEvent event) {
		if (event.getProperty().equals(TaskListPreferenceConstants.PLANNING_STARTHOUR)
				|| event.getProperty().equals(TaskListPreferenceConstants.PLANNING_ENDHOUR)) {
			// event.getProperty().equals(TaskListPreferenceConstants.PLANNING_STARTDAY)
			// scheduledStartHour =
			// TasksUiPlugin.getDefault().getPreferenceStore().getInt(
			// TaskListPreferenceConstants.PLANNING_STARTHOUR);
			scheduledEndHour = TasksUiPlugin.getDefault().getPreferenceStore().getInt(
					TaskListPreferenceConstants.PLANNING_ENDHOUR);
		}
	}

	/** public for testing */
	public void resetAndRollOver() {
		taskActivityHistoryInitialized = false;
		tasksWithReminders.clear();
		tasksWithDueDates.clear();
		for (ITask task : taskList.getAllTasks()) {
			if (task.getScheduledForDate() != null) {
				tasksWithReminders.add(task);
			}
			if (task.getDueDate() != null) {
				tasksWithDueDates.add(task);
			}
		}
		resetActivity();
		parseTaskActivityInteractionHistory();
		for (ITaskActivityListener listener : activityListeners) {
			listener.calendarChanged();
		}
	}

	private class RolloverCheck extends TimerTask {

		@Override
		public void run() {
			if (!Platform.isRunning() || ContextCorePlugin.getDefault() == null) {
				return;
			} else {
				Calendar now = GregorianCalendar.getInstance();
				DateRangeContainer thisWeek = getActivityThisWeek();
				if (!thisWeek.includes(now)) {
					startTime = new Date();
					resetAndRollOver();
				}
			}
		}
	}

	public TaskActivationHistory getTaskActivationHistory() {
		return taskActivityHistory;
	}

	public Set<ITask> getScheduledForThisWeek() {
		Set<ITask> tasksScheduled = new HashSet<ITask>();
		for (ITask task : getActivityThisWeek().getChildren()) {
			if (isScheduledForThisWeek(task)) {
				tasksScheduled.add(task);
			}
		}
		return tasksScheduled;
	}

	/**
	 * @param element
	 *            tasklist element to retrieve a task for currently will work
	 *            for (ITask, AbstractQueryHit)
	 * @param force -
	 *            if a query hit is passed you can either force construction of
	 *            the task or not (if not and no task, null is returned) TODO:
	 *            Move into TaskList?
	 */
	public ITask getTaskForElement(ITaskListElement element, boolean force) {
		ITask task = null;
		if (element instanceof AbstractQueryHit) {
			if (force) {
				task = ((AbstractQueryHit) element).getOrCreateCorrespondingTask();
			} else {
				task = ((AbstractQueryHit) element).getCorrespondingTask();
			}
		} else if (element instanceof ITask) {
			task = (ITask) element;
		}
		return task;
	}

	protected void setTaskListSaveManager(TaskListSaveManager taskListSaveManager) {
		this.taskListSaveManager = taskListSaveManager;
		this.taskList.addChangeListener(taskListSaveManager);
	}

	public List<DateRangeContainer> getActivityWeekDays() {
		return activityWeekDays;
	}

	public boolean isWeekDay(DateRangeContainer dateRangeTaskContainer) {
		return activityWeekDays.contains(dateRangeTaskContainer);
	}

	public int getStartHour() {
		return START_HOUR;
	}
}
