/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation 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:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.html.internal.validation;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;

/**
 * This class must be called only by the validation framework.
 * 
 * This singleton interacts with the eclipse workbench's Task list.
 * TaskListUtility adds and removes tasks from the list.
 * 
 * This class must not be called outside of an IWorkspaceRunnable or
 * IRunnableWithProgress. Many resource deltas can be generated by the methods
 * in this class.
 * 
 * This came from TaskListUtility
 */
public class TaskListUtility {
	// private static final String PLUGIN_ID = ValidationPlugin.PLUGIN_ID;
	private static final String PLUGIN_ID = HTMLUIPlugin.ID;
	private static final String VALIDATION_MARKER = PLUGIN_ID + ".problemmarker"; //$NON-NLS-1$ // The extension which is used to add validation markers to the task list
	private static final String VALIDATION_MARKER_OWNER = "owner"; //$NON-NLS-1$ // The IValidator who owns the IMarker on the task list
	private static final String VALIDATION_MARKER_SEVERITY = "validationSeverity"; //$NON-NLS-1$ // one of the IMessage values
	private static final String VALIDATION_MARKER_TARGETOBJECT = "targetObject"; //$NON-NLS-1$ // When more than one target object resolves to the same IResource, this field identifies which targetObject owns a particular message.
	private static final String VALIDATION_MARKER_GROUP = "groupName"; //$NON-NLS-1$ // For incremental validation, this field associates a message with a group, so that a subset of messages may be removed from a file.
	private static final String VALIDATION_MARKER_MESSAGEID = "messageId"; //$NON-NLS-1$ // Persist the message id of the message, not just the translated text.
	private static final int DEPTH_INFINITE = IResource.DEPTH_INFINITE;
	private static final int DEPTH_ZERO = IResource.DEPTH_ZERO;
	private final static IMarker[] NO_MARKERS = new IMarker[0];

	/**
	 * This method adds a message to a resource in the task list.
	 */
	public static IMarker addTask(String pluginId, IResource resource, String location, String messageId, String message, int markerType, String targetObjectName, String groupName, int offset, int length) throws CoreException {
		if ((message == null) || (resource == null)) {
			return null;
		}

		int severity = getSeverity(markerType);

		// Allow duplicate entries in the task list.
		// Prior to a full validation, the validation framework will remove
		// all messages owned
		// by a validator before it is executed.
		// Prior to an incremental validation, the validation framework will
		// remove all messages,
		// on each of the changed resources, owned by a validator before it is
		// invoked.
		// 
		// It is up to the validator to make sure that it is not adding the
		// same message
		// in more than one place, and also to clear out any old messages
		// which are not cleared
		// by the validation framework.
		IMarker item = resource.createMarker(VALIDATION_MARKER); // add a
																	// validation
																	// marker

		// For performance reasons, replace the multiple setAttribute
		// calls above with a single setAttributes call.
		boolean offsetSet = ((offset != IMessage.OFFSET_UNSET) && (length != IMessage.OFFSET_UNSET));
		int size = (offsetSet) ? 10 : 8; // add CHAR_START, CHAR_END only
											// if the offset is set. If the
											// offset is set, it takes
											// precendence over the line
											// number. (eclipse's rule, not
											// mine.)
		String[] attribNames = new String[size];
		Object[] attribValues = new Object[size];

		// Very first thing, add the owner. That way, if the code dies
		// before things are persisted, hopefully this marker will be
		// persisted.
		// Hopefully, eclipse WILL persist this field, as requested.
		attribNames[0] = VALIDATION_MARKER_OWNER;
		attribValues[0] = pluginId;
		attribNames[1] = VALIDATION_MARKER_SEVERITY; // this validation
														// severity is stored,
														// in addition to the
														// marker severity, to
														// enable more than
														// one severity of
														// message to be
														// displayed. e.g.
														// ERROR | WARNING
														// (using binary OR).
														// The IMarker
														// constants are
														// regular decimal
														// constants.
		attribValues[1] = new Integer(markerType);
		attribNames[2] = VALIDATION_MARKER_TARGETOBJECT; // to distinguish
															// between
															// messages which
															// are registered
															// on an
															// IResource, but
															// against
															// different
															// target objects
		attribValues[2] = ((targetObjectName == null) ? "" : targetObjectName); //$NON-NLS-1$
		attribNames[3] = VALIDATION_MARKER_GROUP;
		attribValues[3] = ((groupName == null) ? "" : groupName); //$NON-NLS-1$
		attribNames[4] = IMarker.MESSAGE;
		attribValues[4] = message;
		attribNames[5] = VALIDATION_MARKER_MESSAGEID;
		attribValues[5] = messageId;

		attribNames[6] = IMarker.SEVERITY; // IMarker.SEVERITY_ERROR,
											// IMarker.SEVERITY_WARNING,
											// IMarker.SEVERITY_INFO
		attribValues[6] = new Integer(severity);
		try {
			// If the location is a line number, store it as a line number
			Integer lineNumber = Integer.valueOf(location);
			attribNames[7] = IMarker.LINE_NUMBER;
			attribValues[7] = lineNumber;
		}
		catch (NumberFormatException exc) {
			// Otherwise, store it as a text location
			attribNames[7] = IMarker.LOCATION;
			attribValues[7] = location;
		}

		if (offsetSet) {
			attribNames[8] = IMarker.CHAR_START;
			attribValues[8] = new Integer(offset);
			attribNames[9] = IMarker.CHAR_END;
			attribValues[9] = new Integer(offset + length);
		}

		item.setAttributes(attribNames, attribValues);

		return item;
	}

	/**
	 * Given one of the SeverityEnum severities, return the IMarker severity
	 * int that is its equivalent.
	 */
	private static int getSeverity(int severityEnumValue) {
		switch (severityEnumValue) {
			case (IMessage.HIGH_SEVERITY) : {
				return IMarker.SEVERITY_ERROR;
			}

			case (IMessage.LOW_SEVERITY) : {
				return IMarker.SEVERITY_INFO;
			}

			case (IMessage.NORMAL_SEVERITY) : {
				return IMarker.SEVERITY_WARNING;
			}

			case (IMessage.ALL_MESSAGES) :
			case (IMessage.ERROR_AND_WARNING) :
			default : {
				// assume it's a warning.
				return IMarker.SEVERITY_WARNING;
			}
		}
	}

	private static int getDepth(IResource resource) {
		if (resource instanceof IProject) {
			return DEPTH_INFINITE; // DEPTH_INFINITE means get this project's
									// markers, and the markers belonging to
									// the project's children.
		}
		else if (resource instanceof IWorkspaceRoot) {
			// Needed for the ValidationMigrator when it checks for orphan
			// tasks.
			return DEPTH_INFINITE; // DEPTH_INFINITE means get all of the
									// markers in the workspace
		}

		return DEPTH_ZERO; // DEPTH_ZERO means just this resource, not its
							// children
	}

	private static IMarker[] getValidationTasks(IResource resource, int severity, int depth) {
		IMarker[] tempMarkers = null;
		int validCount = 0;
		try {
			IMarker[] allMarkers = null;
			try {
				allMarkers = resource.findMarkers(VALIDATION_MARKER, false, depth); // false
																					// means
																					// only
																					// consider
																					// PROBLEM_MARKER,
																					// not
																					// variants
																					// of
																					// PROBLEM_MARKER.
																					// Since
																					// addTask
																					// only
																					// adds
																					// PROBLEM_MARKER,
																					// we
																					// don't
																					// need
																					// to
																					// consider
																					// its
																					// subtypes.
			}
			catch (CoreException exc) {
				// Logger logger =
				// ValidationPlugin.getPlugin().getMsgLogger();
				// if (logger.isLoggingLevel(Level.SEVERE)) {
				// LogEntry entry = ValidationPlugin.getLogEntry();
				// entry.setSourceID("TaskListUtility.getValidationTasks(IResource,
				// int)"); //$NON-NLS-1$
				// entry.setTargetException(exc);
				// logger.write(Level.SEVERE, entry);
				// }
				return NO_MARKERS;
			}

			// Now filter in the markers, based on severity type.
			if (allMarkers.length != 0) {
				tempMarkers = new IMarker[allMarkers.length];
				for (int i = 0; i < allMarkers.length; i++) {
					IMarker marker = allMarkers[i];
					Integer filterSeverity = (Integer) marker.getAttribute(VALIDATION_MARKER_SEVERITY);
					if (filterSeverity == null) {
						// odd...marker wasn't created correctly. How could
						// this happen?
						// Default to the current severity and add it to the
						// list.
						try {
							marker.setAttribute(IMarker.SEVERITY, getSeverity(severity));
						}
						catch (CoreException exc) {
							// Logger logger =
							// ValidationPlugin.getPlugin().getMsgLogger();
							// if (logger.isLoggingLevel(Level.SEVERE)) {
							// LogEntry entry =
							// ValidationPlugin.getLogEntry();
							// entry.setSourceID("TaskListUtility.getValidationTasks(int,
							// IResource, int)"); //$NON-NLS-1$
							// entry.setTargetException(exc);
							// logger.write(Level.SEVERE, entry);
							// }
							continue;
						}
						catch (Throwable exc) {
							// Logger logger =
							// ValidationPlugin.getPlugin().getMsgLogger();
							// if (logger.isLoggingLevel(Level.SEVERE)) {
							// LogEntry entry =
							// ValidationPlugin.getLogEntry();
							// entry.setSourceID("TaskListUtility.getValidationTasks(int,
							// IResource, int)"); //$NON-NLS-1$
							// entry.setTargetException(exc);
							// logger.write(Level.SEVERE, entry);
							// }
							continue;
						}
					}
					else if ((severity & filterSeverity.intValue()) == 0) {
						continue;
					}
					tempMarkers[validCount++] = marker;
				}
			}
		}
		catch (CoreException exc) {
			// Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			// if (logger.isLoggingLevel(Level.SEVERE)) {
			// LogEntry entry = ValidationPlugin.getLogEntry();
			// entry.setSourceID("TaskListUtility.getValidationTasks(int,
			// IResource, int)"); //$NON-NLS-1$
			// entry.setTargetException(exc);
			// logger.write(Level.SEVERE, entry);
			// }
		}

		if (validCount == 0) {
			return NO_MARKERS;
		}

		IMarker[] validMarkers = new IMarker[validCount];
		System.arraycopy(tempMarkers, 0, validMarkers, 0, validCount);
		return validMarkers;
	}

	private static IMarker[] getValidationTasks(IResource resource, String[] messageOwners, int depth) {
		IMarker[] markers = getValidationTasks(resource, IMessage.ALL_MESSAGES, depth);
		if (markers.length == 0) {
			return NO_MARKERS;
		}

		IMarker[] temp = new IMarker[markers.length];
		int validCount = 0;
		for (int i = 0; i < markers.length; i++) {
			IMarker marker = markers[i];

			try {
				Object owner = marker.getAttribute(VALIDATION_MARKER_OWNER);
				if ((owner == null) || !(owner instanceof String)) {
					// The ValidationMigrator will remove any "unowned"
					// validation markers.
					continue;
				}

				for (int j = 0; j < messageOwners.length; j++) {
					String messageOwner = messageOwners[j];
					if (((String) owner).equals(messageOwner)) {
						temp[validCount++] = marker;
						break;
					}
				}
			}
			catch (CoreException exc) {
				// Logger logger =
				// ValidationPlugin.getPlugin().getMsgLogger();
				// if (logger.isLoggingLevel(Level.SEVERE)) {
				// LogEntry entry = ValidationPlugin.getLogEntry();
				// entry.setSourceID("TaskListUtility.getValidationTasks(project,
				// String[])"); //$NON-NLS-1$
				// entry.setTargetException(exc);
				// logger.write(Level.SEVERE, entry);
				// }
				return NO_MARKERS;
			}
		}

		IMarker[] result = new IMarker[validCount];
		System.arraycopy(temp, 0, result, 0, validCount);
		return result;
	}

	/**
	 * This method retrieves all validation tasks from the resource. If depth
	 * is INFINITE, child tasks are returned as well. Only the tasks which are
	 * owned by the specified messageOwner, and apply to the named IMessage's
	 * target object (objectName) will be returned.
	 */
	private static IMarker[] getValidationTasks(IResource resource, String[] messageOwner, String objectName, String groupName, int depth) throws CoreException {
		if ((messageOwner == null) || (resource == null)) {
			return NO_MARKERS;
		}

		int validCount = 0;
		IMarker[] validList = null;
		IMarker[] markers = getValidationTasks(resource, messageOwner, depth);
		if (markers != null) {
			validList = new IMarker[markers.length];
			for (int i = 0; i < markers.length; i++) {
				IMarker marker = markers[i];

				// If more than one target object resolves to the same
				// resource, removing one target's
				// messages should not remove the other target object's
				// messages.
				if (objectName != null) {
					Object targetObject = marker.getAttribute(VALIDATION_MARKER_TARGETOBJECT);
					if ((targetObject == null) || !(targetObject instanceof String) || !(((String) targetObject).equals(objectName))) {
						continue;
					}
				}

				if (groupName != null) {
					Object group = marker.getAttribute(VALIDATION_MARKER_GROUP);
					if ((group == null) || !(group instanceof String) || !(((String) group).equals(groupName))) {
						continue;
					}
				}

				validList[validCount++] = marker;
			}
		}

		if (validCount == 0) {
			return NO_MARKERS;
		}

		IMarker[] result = new IMarker[validCount];
		System.arraycopy(validList, 0, result, 0, validCount);
		return result;
	}

	/**
	 * This method removes all messages from a resource in the task list.
	 */
	public static void removeAllTasks(IResource resource, String owner, String objectName) throws CoreException {
		removeAllTasks(resource, new String[]{owner}, objectName);
	}

	public static void removeAllTasks(IResource resource, String[] owners, String objectName) throws CoreException {
		removeAllTasks(resource, owners, objectName, getDepth(resource));
	}

	protected static void removeAllTasks(IResource resource, String[] owners, String objectName, int depth) throws CoreException {
		removeTaskSubset(resource, owners, objectName, null, depth); // null
																		// means
																		// no
																		// group
																		// name
	}

	/**
	 * This method removes a subset of tasks from the project, including child
	 * tasks. Every task which belongs to the group, identified by groupName,
	 * will be removed.
	 */
	protected static void removeTaskSubset(IResource resource, String[] owners, String objectName, String groupName, int depth) throws CoreException {
		if ((owners == null) || (resource == null)) {
			return;
		}

		IMarker[] allTasks = getValidationTasks(resource, owners, objectName, groupName, depth);
		if (allTasks.length > 0) {
			ResourcesPlugin.getWorkspace().deleteMarkers(allTasks);
		}
	}
}