/*******************************************************************************
 * Copyright (c) 2004, 2011 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.tasks.core;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.net.Policy;
import org.eclipse.mylyn.tasks.core.IRepositoryElement;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState;

/**
 * Stores and manages task list elements and their containment hierarchy.
 *
 * @author Mik Kersten
 * @author Rob Elves
 * @since 3.0
 */
public class TaskList implements ITaskList, ITransferList {

	private static String DEFAULT_HANDLE_PREFIX = "handle-"; //$NON-NLS-1$

	private static ILock lock = Job.getJobManager().newLock();

	private Map<String, AbstractTaskCategory> categories;

	private final Set<ITaskListChangeListener> changeListeners = new CopyOnWriteArraySet<ITaskListChangeListener>();

	private UncategorizedTaskContainer defaultCategory;

	private int maxLocalTaskId;

	private Map<String, RepositoryQuery> queries;

	private Map<String, UnmatchedTaskContainer> unmatchedMap;

	private Map<String, UnsubmittedTaskContainer> unsubmittedTasksMap;

	private Map<String, AbstractTask> tasks;

	private Set<TaskContainerDelta> delta;

	private int nextHandle = 1;

	public TaskList() {
		reset();
	}

	public void addCategory(TaskCategory category) {
		Assert.isNotNull(category);
		try {
			lock();
			if (categories.containsKey(category.getHandleIdentifier())) {
				throw new IllegalArgumentException("Handle " + category.getHandleIdentifier() //$NON-NLS-1$
						+ " already exists in task list"); //$NON-NLS-1$
			}
			categories.put(category.getHandleIdentifier(), category);
			delta.add(new TaskContainerDelta(category, TaskContainerDelta.Kind.ADDED));
		} finally {
			unlock();
		}
	}

	public void addChangeListener(ITaskListChangeListener listener) {
		changeListeners.add(listener);
	}

	/**
	 * precondition: task must not be null and must exist in the task list
	 */
	private void addToUnmatched(AbstractTask task, Set<TaskContainerDelta> delta) {
		if (!task.getParentContainers().isEmpty()) {
			// Current policy is not to archive/orphan if the task exists in some other container
			return;
		}

		AbstractTaskContainer orphans = getUnmatchedContainer(task.getRepositoryUrl());
		if (orphans != null) {
			task.addParentContainer(orphans);
			orphans.internalAddChild(task);
			delta.add(new TaskContainerDelta(task, orphans, TaskContainerDelta.Kind.ADDED));
		}
	}

	public void addQuery(RepositoryQuery query) throws IllegalArgumentException {
		Assert.isNotNull(query);
		try {
			lock();
			if (queries.containsKey(query.getHandleIdentifier())) {
				throw new IllegalArgumentException("Handle " + query.getHandleIdentifier() //$NON-NLS-1$
						+ " already exists in task list"); //$NON-NLS-1$
			}
			queries.put(query.getHandleIdentifier(), query);
			delta.add(new TaskContainerDelta(query, TaskContainerDelta.Kind.ADDED));
		} finally {
			unlock();
		}
	}

	/**
	 * Add task to default category if it's not in the task list.
	 */
	public boolean addTaskIfAbsent(ITask task) {
		if (getTask(task.getRepositoryUrl(), task.getTaskId()) == null) {
			addTask(task, getDefaultCategory());
			return true;
		}
		return false;
	}

	/**
	 * Add orphaned task to the task list
	 */
	public void addTask(ITask task) {
		addTask(task, null);
	}

	public boolean addTask(ITask itask, AbstractTaskContainer container) {
		AbstractTask task = (AbstractTask) itask;
		Assert.isNotNull(task);
		Assert.isLegal(!(container instanceof UnmatchedTaskContainer));

		try {
			lock();
			task = getOrCreateTask(task);
			if (task.getSynchronizationState() == SynchronizationState.OUTGOING_NEW) {
				String repositoryUrl = task.getAttribute(ITasksCoreConstants.ATTRIBUTE_OUTGOING_NEW_REPOSITORY_URL);
				if (repositoryUrl != null) {
					container = getUnsubmittedContainer(repositoryUrl);
				}
			}
			if (container == null) {
				container = getUnmatchedContainer(task.getRepositoryUrl());
			} else {
				container = getValidElement(container);
			}

			if (container instanceof UnsubmittedTaskContainer && container.isEmpty()) {
				delta.add(new TaskContainerDelta(container, TaskContainerDelta.Kind.ROOT));
			}

			// ensure parent is valid and does not contain task already
			if (container == null || task.equals(container) || task.getParentContainers().contains(container)) {
				return false;
			}

			// ensure that we don't create cycles
			if ((task).contains(container.getHandleIdentifier())) {
				return false;
			}

			if (task instanceof LocalTask && task.getParentContainers().size() > 0) {
				// local tasks should only have 1 parent
				for (AbstractTaskContainer parent : task.getParentContainers()) {
					removeFromContainerInternal(parent, task, delta);
				}
			} else if (container instanceof AbstractTaskCategory) {
				// tasks can only be in one task category at a time
				AbstractTaskCategory tempCat = TaskCategory.getParentTaskCategory(task);
				if (tempCat != null) {
					removeFromContainerInternal(tempCat, task, delta);
				}
			}

			if (!(container instanceof UnmatchedTaskContainer)) {
				removeFromUnmatched(task, delta);
			}

			task.addParentContainer(container);
			container.internalAddChild(task);
			delta.add(new TaskContainerDelta(task, container, TaskContainerDelta.Kind.ADDED));
		} finally {
			unlock();
		}

		return true;
	}

	public void addUnmatchedContainer(UnmatchedTaskContainer orphanedTasksContainer) {
		unmatchedMap.put(orphanedTasksContainer.getRepositoryUrl(), orphanedTasksContainer);
		unsubmittedTasksMap.put(orphanedTasksContainer.getRepositoryUrl(), new UnsubmittedTaskContainer(
				orphanedTasksContainer.getConnectorKind(), orphanedTasksContainer.getRepositoryUrl()));
	}

	public void deleteCategory(AbstractTaskCategory category) {
		try {
			lock();
			categories.remove(category.getHandleIdentifier());
			for (ITask task : category.getChildren()) {
				((AbstractTask) task).removeParentContainer(category);
				addToUnmatched((AbstractTask) task, delta);
			}
			delta.add(new TaskContainerDelta(category, TaskContainerDelta.Kind.REMOVED));
			delta.add(new TaskContainerDelta(category, TaskContainerDelta.Kind.DELETED));
		} finally {
			unlock();
		}
	}

	public void deleteQuery(RepositoryQuery query) {
		try {
			lock();
			queries.remove(query.getHandleIdentifier());
			for (ITask task : query.getChildren()) {
				((AbstractTask) task).removeParentContainer(query);
				addToUnmatched((AbstractTask) task, delta);
			}
			delta.add(new TaskContainerDelta(query, TaskContainerDelta.Kind.REMOVED));
			delta.add(new TaskContainerDelta(query, TaskContainerDelta.Kind.DELETED));
		} finally {
			unlock();
		}
	}

	/**
	 * Task is removed from all containers. Currently subtasks are not deleted but rather are rather potentially
	 * orphaned.
	 */
	public void deleteTask(ITask itask) {
		Assert.isNotNull(itask);
		AbstractTask task = (AbstractTask) itask;
		try {
			lock();

			// remove task from all parent containers
			for (AbstractTaskContainer container : task.getParentContainers()) {
				removeFromContainerInternal(container, task, delta);
			}

			// remove this task as a parent for all subtasks
			for (ITask child : task.getChildren()) {
				removeFromContainerInternal(task, child, delta);
				addToUnmatched((AbstractTask) child, delta);
			}

			tasks.remove(task.getHandleIdentifier());
			delta.add(new TaskContainerDelta(task, TaskContainerDelta.Kind.REMOVED));
			delta.add(new TaskContainerDelta(task, TaskContainerDelta.Kind.DELETED));
		} finally {
			unlock();
		}
	}

	private void fireDelta(HashSet<TaskContainerDelta> deltasToFire) {
		for (ITaskListChangeListener listener : changeListeners) {
			try {
				listener.containersChanged(Collections.unmodifiableSet(deltasToFire));
			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Notification failed for: " //$NON-NLS-1$
						+ listener, t));
			}
		}
	}

	public Collection<AbstractTask> getAllTasks() {
		return Collections.unmodifiableCollection(tasks.values());
	}

	public Set<AbstractTaskCategory> getCategories() {
		return Collections.unmodifiableSet(new HashSet<AbstractTaskCategory>(categories.values()));
	}

	/**
	 * Exposed for unit testing
	 *
	 * @return unmodifiable collection of ITaskActivityListeners
	 */
	public Set<ITaskListChangeListener> getChangeListeners() {
		return Collections.unmodifiableSet(changeListeners);
	}

	public AbstractTaskCategory getContainerForHandle(String categoryHandle) {
		Assert.isNotNull(categoryHandle);
		for (AbstractTaskCategory cat : categories.values()) {
			if (cat.getHandleIdentifier().equals(categoryHandle)) {
				return cat;
			}
		}
		return null;
	}

	public AbstractTaskCategory getDefaultCategory() {
		return defaultCategory;
	}

	public int getLastLocalTaskId() {
		return maxLocalTaskId;
	}

	public int getNextLocalTaskId() {
		try {
			lock();
			return ++maxLocalTaskId;
		} finally {
			unlock();
		}
	}

	private AbstractTask getOrCreateTask(AbstractTask taskListElement) {
		AbstractTask task = tasks.get(taskListElement.getHandleIdentifier());
		if (task == null) {
			tasks.put(taskListElement.getHandleIdentifier(), taskListElement);
			task = taskListElement;
			if (task instanceof LocalTask) {
				try {
					int taskId = Integer.parseInt(task.getTaskId());
					maxLocalTaskId = Math.max(maxLocalTaskId, taskId);
				} catch (NumberFormatException e) {
					// ignore
				}
			}
		}
		return task;
	}

	public Set<RepositoryQuery> getQueries() {
		return Collections.unmodifiableSet(new HashSet<RepositoryQuery>(queries.values()));
	}

	/**
	 * return all queries for the given repository url
	 */
	public Set<RepositoryQuery> getRepositoryQueries(String repositoryUrl) {
		Assert.isNotNull(repositoryUrl);

		Set<RepositoryQuery> repositoryQueries = new HashSet<RepositoryQuery>();
		for (RepositoryQuery query : queries.values()) {
			if (query.getRepositoryUrl().equals(repositoryUrl)) {
				repositoryQueries.add(query);
			}
		}
		return repositoryQueries;
	}

	public Set<AbstractTaskContainer> getRootElements() {
		Set<AbstractTaskContainer> roots = new HashSet<AbstractTaskContainer>();
		roots.add(defaultCategory);
		for (AbstractTaskCategory cat : categories.values()) {
			roots.add(cat);
		}
		for (RepositoryQuery query : queries.values()) {
			roots.add(query);
		}
		for (UnmatchedTaskContainer orphanContainer : unmatchedMap.values()) {
			roots.add(orphanContainer);
		}
		for (UnsubmittedTaskContainer unsubmitedTaskContainer : unsubmittedTasksMap.values()) {
			roots.add(unsubmitedTaskContainer);
		}
		return roots;
	}

	/**
	 * TODO: consider removing, if everything becomes a repository task
	 *
	 * @return null if no such task.
	 */
	public AbstractTask getTask(String handleIdentifier) {
		if (handleIdentifier == null) {
			return null;
		} else {
			return tasks.get(handleIdentifier);
		}
	}

	public ITask getTask(String repositoryUrl, String taskId) {
		if (!RepositoryTaskHandleUtil.isValidTaskId(taskId)) {
			return null;
		}

		String handle = RepositoryTaskHandleUtil.getHandle(repositoryUrl, taskId);
		return getTask(handle);
	}

	public AbstractTask getTaskByKey(String repositoryUrl, String taskKey) {
		for (AbstractTask task : tasks.values()) {
			String currentTaskKey = task.getTaskKey();
			if (currentTaskKey != null && currentTaskKey.equals(taskKey)
					&& task.getRepositoryUrl().equals(repositoryUrl)) {
				return task;
			}
		}
		return null;
	}

	public Set<AbstractTaskCategory> getTaskCategories() {
		Set<AbstractTaskCategory> containers = new HashSet<AbstractTaskCategory>();
		for (AbstractTaskCategory container : categories.values()) {
			if (container instanceof TaskCategory) {
				containers.add(container);
			}
		}
		return containers;
	}

	/**
	 * Returns all tasks for the given repository url.
	 */
	public Set<ITask> getTasks(String repositoryUrl) {
		Set<ITask> repositoryTasks = new HashSet<ITask>();
		if (repositoryUrl != null) {
			for (ITask task : tasks.values()) {
				if (task.getRepositoryUrl().equals(repositoryUrl)) {
					repositoryTasks.add(task);
				}
			}
		}
		return repositoryTasks;
	}

	public AbstractTaskContainer getUnmatchedContainer(String repositoryUrl) {
		if (LocalRepositoryConnector.REPOSITORY_URL.equals(repositoryUrl)) {
			return defaultCategory;
		} else {
			UnmatchedTaskContainer unmatched = unmatchedMap.get(repositoryUrl);
			if (unmatched == null) {
				StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
						"Failed to find unmatched container for repository \"" + repositoryUrl + "\"")); //$NON-NLS-1$ //$NON-NLS-2$
			}
			return unmatched;
		}
	}

	public Set<UnmatchedTaskContainer> getUnmatchedContainers() {
		return Collections.unmodifiableSet(new HashSet<UnmatchedTaskContainer>(unmatchedMap.values()));
	}

	/**
	 * Task added if does not exist already. Ensures the element exists in the task list
	 *
	 * @throws IllegalAgumentException
	 *             if null argument passed or element does not exist in task list
	 * @return element as passed in or instance from task list with same handle if exists
	 */
	private AbstractTaskContainer getValidElement(IRepositoryElement taskListElement) {
		AbstractTaskContainer result = null;
		if (taskListElement instanceof ITask) {
			result = tasks.get(taskListElement.getHandleIdentifier());
		} else if (taskListElement instanceof UncategorizedTaskContainer) {
			result = defaultCategory;
		} else if (taskListElement instanceof UnmatchedTaskContainer) {
			result = unmatchedMap.get(((UnmatchedTaskContainer) taskListElement).getRepositoryUrl());
		} else if (taskListElement instanceof UnsubmittedTaskContainer) {
			result = unsubmittedTasksMap.get(((UnsubmittedTaskContainer) taskListElement).getRepositoryUrl());
		} else if (taskListElement instanceof TaskCategory) {
			result = categories.get(taskListElement.getHandleIdentifier());
		} else if (taskListElement instanceof IRepositoryQuery) {
			result = queries.get(taskListElement.getHandleIdentifier());
		}

		if (result == null) {
			throw new IllegalArgumentException("Element " + taskListElement.getHandleIdentifier() //$NON-NLS-1$
					+ " does not exist in the task list."); //$NON-NLS-1$
		} else {
			return result;
		}
	}

	public void notifyElementsChanged(Set<? extends IRepositoryElement> elements) {
		HashSet<TaskContainerDelta> deltas = new HashSet<TaskContainerDelta>();
		if (elements == null) {
			deltas.add(new TaskContainerDelta(null, TaskContainerDelta.Kind.ROOT));
		} else {
			for (IRepositoryElement element : elements) {
				deltas.add(new TaskContainerDelta(element, TaskContainerDelta.Kind.CONTENT));
			}
		}

		fireDelta(deltas);
	}

	// TODO rename: this indicates a change of the synchronizing/status flag, not of the synchronization state
	public void notifySynchronizationStateChanged(Set<? extends IRepositoryElement> elements) {
		HashSet<TaskContainerDelta> taskChangeDeltas = new HashSet<TaskContainerDelta>();
		for (IRepositoryElement abstractTaskContainer : elements) {
			TaskContainerDelta delta = new TaskContainerDelta(abstractTaskContainer, TaskContainerDelta.Kind.CONTENT);
			delta.setTransient(true);
			taskChangeDeltas.add(delta);
		}

		fireDelta(taskChangeDeltas);
	}

	// TODO rename: this indicates a change of the synchronizing/status flag, not of the synchronization state
	public void notifySynchronizationStateChanged(IRepositoryElement element) {
		notifySynchronizationStateChanged(Collections.singleton(element));
	}

	public void notifyElementChanged(IRepositoryElement element) {
		notifyElementsChanged(Collections.singleton(element));
	}

	public void refactorRepositoryUrl(String oldRepositoryUrl, String newRepositoryUrl) {
		Assert.isNotNull(oldRepositoryUrl);
		Assert.isNotNull(newRepositoryUrl);

		try {
			lock();
			for (AbstractTask task : tasks.values()) {
				if (oldRepositoryUrl.equals(RepositoryTaskHandleUtil.getRepositoryUrl(task.getHandleIdentifier()))) {
					tasks.remove(task.getHandleIdentifier());
					task.setRepositoryUrl(newRepositoryUrl);
					tasks.put(task.getHandleIdentifier(), task);
					String taskUrl = task.getUrl();
					if (taskUrl != null && taskUrl.startsWith(oldRepositoryUrl)) {
						task.setUrl(newRepositoryUrl + taskUrl.substring(oldRepositoryUrl.length()));
					}
				}
				if (oldRepositoryUrl
						.equals(task.getAttribute(ITasksCoreConstants.ATTRIBUTE_OUTGOING_NEW_REPOSITORY_URL))) {
					task.setAttribute(ITasksCoreConstants.ATTRIBUTE_OUTGOING_NEW_REPOSITORY_URL, newRepositoryUrl);
				}
			}

			for (RepositoryQuery query : queries.values()) {
				if (query.getRepositoryUrl().equals(oldRepositoryUrl)) {
					query.setRepositoryUrl(newRepositoryUrl);
					delta.add(new TaskContainerDelta(query, TaskContainerDelta.Kind.CONTENT));
				}
			}

			for (UnmatchedTaskContainer unmatched : unmatchedMap.values()) {
				if (unmatched.getRepositoryUrl().equals(oldRepositoryUrl)) {
					unmatchedMap.remove(oldRepositoryUrl);
					//categories.remove(orphans.getHandleIdentifier());
					unmatched.setRepositoryUrl(newRepositoryUrl);
					unmatchedMap.put(newRepositoryUrl, unmatched);
					//categories.put(orphans.getHandleIdentifier(), orphans);
					delta.add(new TaskContainerDelta(unmatched, TaskContainerDelta.Kind.CONTENT));
				}
			}
			for (UnsubmittedTaskContainer unsubmitted : unsubmittedTasksMap.values()) {
				if (unsubmitted.getRepositoryUrl().equals(oldRepositoryUrl)) {
					unsubmittedTasksMap.remove(oldRepositoryUrl);
					unsubmitted.setRepositoryUrl(newRepositoryUrl);
					unsubmittedTasksMap.put(newRepositoryUrl, unsubmitted);
					delta.add(new TaskContainerDelta(unsubmitted, TaskContainerDelta.Kind.CONTENT));
				}
			}
		} finally {
			unlock();
		}
	}

	public AbstractTask refactorTaskId(ITask oldTask, String newTaskId) {
		TaskTask newTask = new TaskTask(oldTask.getConnectorKind(), oldTask.getRepositoryUrl(), newTaskId);

		newTask.setSummary(oldTask.getSummary());
		newTask.setPriority(oldTask.getPriority());
		newTask.setSynchronizationState(oldTask.getSynchronizationState());
		newTask.setCompletionDate(oldTask.getCompletionDate());
		newTask.setCreationDate(oldTask.getCreationDate());
		newTask.setModificationDate(oldTask.getModificationDate());
		newTask.setTaskKind(oldTask.getTaskKind());
		newTask.setOwnerId(oldTask.getOwnerId());
		newTask.setOwner(oldTask.getOwner());
		newTask.setTaskKey(oldTask.getTaskKey());
		if (oldTask instanceof AbstractTask) {
			AbstractTask task = (AbstractTask) oldTask;
			newTask.setSynchronizing(task.isSynchronizing());
			newTask.setMarkReadPending(task.isMarkReadPending());
			newTask.setNotified(task.isNotified());
			newTask.setChanged(task.isChanged());
			newTask.setReminded(task.isReminded());
			newTask.setStatus(task.getStatus());
			newTask.setNotes(task.getNotes());
			newTask.setEstimatedTimeHours(task.getEstimatedTimeHours());
			newTask.setUrl(task.getUrl());
			addTaskContainers(task, newTask);
		}
		Map<String, String> attributeMap = oldTask.getAttributes();
		for (String key : attributeMap.keySet()) {
			newTask.setAttribute(key, attributeMap.get(key));
		}

		deleteTask(oldTask);
		return newTask;
	}

	private void addTaskContainers(AbstractTask oldTask, AbstractTask newTask) {
		Set<AbstractTaskContainer> containers = oldTask.getParentContainers();
		if (containers.isEmpty()
				|| (containers.size() == 1 && containers.iterator().next() instanceof UnmatchedTaskContainer)) {
			addTask(newTask);
		} else {
			for (AbstractTaskContainer container : containers) {
				addTask(newTask, container);
			}
		}
		for (ITask subtask : oldTask.getChildren()) {
			addTask(subtask, newTask);
		}
	}

	public void removeChangeListener(ITaskListChangeListener listener) {
		changeListeners.remove(listener);
	}

	public void removeFromContainer(AbstractTaskContainer container, ITask task) {
		Assert.isNotNull(container);
		Assert.isNotNull(task);

		removeFromContainer(container, Collections.singleton(task));
	}

	public void removeFromContainer(AbstractTaskContainer container, Set<ITask> tasks) {
		Assert.isNotNull(container);
		Assert.isNotNull(tasks);
		try {
			lock();
			for (ITask task : tasks) {
				removeFromContainerInternal(container, task, delta);
				addToUnmatched((AbstractTask) task, delta);
			}
		} finally {
			unlock();
		}
	}

	/**
	 * Note: does not add <code>task</code> to the unmatched container.
	 */
	private void removeFromContainerInternal(AbstractTaskContainer container, ITask task,
			Set<TaskContainerDelta> delta) {
		assert container.getChildren().contains(task);

		container.internalRemoveChild(task);
		((AbstractTask) task).removeParentContainer(container);

		delta.add(new TaskContainerDelta(task, container, TaskContainerDelta.Kind.REMOVED));
	}

	private void removeFromUnmatched(AbstractTask task, Set<TaskContainerDelta> delta) {
		AbstractTaskContainer unmatched = getUnmatchedContainer(task.getRepositoryUrl());
		if (unmatched != null) {
			// first check that the task has the unmatched container as a parent
			// this provides considerable performance improvements when loading large task lists
			if (task.getParentContainers().contains(unmatched) && unmatched.internalRemoveChild(task)) {
				delta.add(new TaskContainerDelta(task, unmatched, TaskContainerDelta.Kind.REMOVED));
				task.removeParentContainer(unmatched);
			}
		}
	}

	/**
	 * TODO separate category/query handle from name
	 *
	 * @deprecated
	 */
	@Deprecated
	public void renameContainer(AbstractTaskContainer container, String newDescription) {
		Assert.isLegal(!(container instanceof ITask));
		Assert.isLegal(!(container instanceof UnmatchedTaskContainer));
		try {
			lock();
			if (container instanceof TaskCategory) {
				((TaskCategory) container).setSummary(newDescription);
			} else if (container instanceof RepositoryQuery) {
				((RepositoryQuery) container).setSummary(newDescription);
			}
			delta.add(new TaskContainerDelta(container, TaskContainerDelta.Kind.CONTENT));
		} finally {
			unlock();
		}
	}

	/**
	 * Public for testing.
	 */
	public void reset() {
		try {
			lock();
			tasks = new ConcurrentHashMap<String, AbstractTask>();

			unmatchedMap = new ConcurrentHashMap<String, UnmatchedTaskContainer>();
			unsubmittedTasksMap = new ConcurrentHashMap<String, UnsubmittedTaskContainer>();
			categories = new ConcurrentHashMap<String, AbstractTaskCategory>();
			queries = new ConcurrentHashMap<String, RepositoryQuery>();

			defaultCategory = new UncategorizedTaskContainer();

			maxLocalTaskId = 0;
			categories.put(defaultCategory.getHandleIdentifier(), defaultCategory);
		} finally {
			unlock();
		}
	}

	public void run(ITaskListRunnable runnable) throws CoreException {
		run(runnable, null);
	}

	public void run(ITaskListRunnable runnable, IProgressMonitor monitor) throws CoreException {
		run(runnable, monitor, false);
	}

	public void run(ITaskListRunnable runnable, IProgressMonitor monitor, boolean ignoreInterrupts)
			throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			lock(monitor, ignoreInterrupts);

			runnable.execute(monitor);

		} finally {
			unlock();
		}
	}

	private void lock() {
		lock.acquire();
		if (lock.getDepth() == 1) {
			delta = new HashSet<TaskContainerDelta>();
		}
	}

	private void lock(IProgressMonitor monitor, boolean ignoreInterrupts) throws CoreException {
		while (!monitor.isCanceled()) {
			try {
				if (lock.acquire(3000)) {
					if (lock.getDepth() == 1) {
						delta = new HashSet<TaskContainerDelta>();
					}
					// success
					return;
				}
			} catch (InterruptedException e) {
				if (ignoreInterrupts) {
					// clear interrupted status to retry lock.aquire()
					Thread.interrupted();
				} else {
					break;
				}
			}
		}
		throw new OperationCanceledException();
	}

	private void unlock() {
		HashSet<TaskContainerDelta> toFire = null;
		try {
			if (lock.getDepth() == 1) {
				toFire = new HashSet<TaskContainerDelta>(delta);
			}
		} finally {
			lock.release();
		}
		if (toFire != null && toFire.size() > 0) {
			fireDelta(toFire);
		}
	}

	public static ISchedulingRule getSchedulingRule() {
		return ITasksCoreConstants.TASKLIST_SCHEDULING_RULE;
	}

	public String getUniqueHandleIdentifier() {
		try {
			lock();
			while (nextHandle < Integer.MAX_VALUE) {
				String handle = DEFAULT_HANDLE_PREFIX + nextHandle;
				nextHandle++;
				if (!categories.containsKey(handle) && !queries.containsKey(handle) && !unmatchedMap.containsKey(handle)
						&& !tasks.containsKey(handle)) {
					return handle;
				}
			}
			throw new RuntimeException("No more unique handles for task list"); //$NON-NLS-1$
		} finally {
			unlock();
		}
	}

	public UnsubmittedTaskContainer getUnsubmittedContainer(String repositoryUrl) {
		return unsubmittedTasksMap.get(repositoryUrl);
	}

}
