/*******************************************************************************
 * Copyright (c) 2001, 2004 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.validation.internal;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.wst.validation.core.SeverityEnum;
import org.eclipse.wst.validation.internal.operations.ValidatorManager;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;

import com.ibm.wtp.common.logger.LogEntry;
import com.ibm.wtp.common.logger.proxy.Logger;

/**
 * This class migrates the following: 1. if a validator class name changes, its old messages must be
 * updated to use the new class name
 * 
 * Also, if a validator is not installed any more, its old messages are removed by this class'
 * removeOrphanedTasks() method.
 */
public final class ValidationMigrator implements ConfigurationConstants {
	private static ValidationMigrator _inst = null;
	private final static IMarker[] NO_MARKERS = new IMarker[0];
	private IWorkspaceRunnable _workspaceMigrator = null;
	private IWorkspaceRunnable _projectMigrator = null;

	// This interface is needed so that migration of an IProject can be done inside
	// an IWorkspaceRunnable (i.e., one build instead of many).
	interface ProjectMigrator extends IWorkspaceRunnable {
		public void setProject(IProject project);

		public IProject getProject();
	}


	private ValidationMigrator() {
	}

	public static ValidationMigrator singleton() {
		if (_inst == null) {
			_inst = new ValidationMigrator();
		}
		return _inst;
	}

	private IWorkspaceRunnable getGlobalMigrator() {
		if (_workspaceMigrator == null) {
			_workspaceMigrator = new IWorkspaceRunnable() {
				public void run(IProgressMonitor monitor) {
					try {
						// Whether the workspace has been migrated or not, check for orphan markers
						// and remove them.
						IWorkspaceRoot root = TaskListUtility.getRoot();
						removeOrphanTasks(monitor, root);

						GlobalConfiguration gp = ConfigurationManager.getManager().getGlobalConfiguration();
						if (gp.isVersionCurrent()) {
							// Workspace has already been migrated. Don't re-migrate the workspace,
							// and don't re-migrate the projects in the workspace.
							//    1. Since this is the current version, all open projects have already
							// been migrated once.
							//    2. Any project that isn't open can't be migrated
							//    3. Any project that was opened after the workspace was migrated is
							// itself migrated on the "OPEN" notification
							return;
						}

						// Do not migrate all of the validators or the projects; let the project
						// migration take care of that step once validation has been awoken on
						// the project.

						// Once all of the migration is complete, mark the preference as current.
						gp.markVersionCurrent();
					} catch (InvocationTargetException exc) {
						Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
						if (logger.isLoggingLevel(Level.SEVERE)) {
							LogEntry entry = ValidationPlugin.getLogEntry();
							entry.setSourceIdentifier("ValidationMigrator.migrate"); //$NON-NLS-1$
							entry.setTargetException(exc);
							logger.write(Level.SEVERE, entry);

							if (exc.getTargetException() != null) {
								entry.setTargetException(exc.getTargetException());
								logger.write(Level.SEVERE, entry);
							}
						}
					}
				}
			};
		}
		return _workspaceMigrator;
	}

	private IWorkspaceRunnable getProjectMigrator(IProject project) {
		if (_projectMigrator == null) {
			_projectMigrator = new ProjectMigrator() {
				private IProject _project = null;

				public void setProject(IProject project) {
					_project = project;
				}

				public IProject getProject() {
					return _project;
				}

				public void run(IProgressMonitor monitor) {
					try {
						// orphan tasks (i.e., IMarkers that are corrupt) need to be removed
						// periodically,
						// instead of once when a project is migrated. If a project is migrated but
						// has
						// orphan tasks, the user can close & reopen the project to have the orphan
						// tasks
						// removed.
						removeOrphanTasks(monitor, getProject());

						ProjectConfiguration prjp = ConfigurationManager.getManager().getProjectConfiguration(getProject());
						if (prjp.isVersionCurrent()) {
							// Project has already been migrated.
							return;
						}

						migrateValidator(monitor, ValidationRegistryReader.getReader().getValidatorMetaData(getProject()), getProject());
						migrateBuilder(monitor, getProject());

						// Once all of the migration is complete, migrate the version number of the
						// preferences
						prjp.markVersionCurrent();
					} catch (InvocationTargetException exc) {
						Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
						if (logger.isLoggingLevel(Level.SEVERE)) {
							LogEntry entry = ValidationPlugin.getLogEntry();
							entry.setSourceIdentifier("ValidationMigrator.migrateBuilder"); //$NON-NLS-1$
							entry.setTargetException(exc);
							logger.write(Level.SEVERE, entry);

							if (exc.getTargetException() != null) {
								entry.setTargetException(exc.getTargetException());
								logger.write(Level.SEVERE, entry);
							}
						}
					}
				}
			};
		}
		((ProjectMigrator) _projectMigrator).setProject(project);
		return _projectMigrator;
	}

	public void migrateRoot(IProgressMonitor monitor) {
		boolean wasSuspended = ValidatorManager.getManager().isSuspended();
		try {
			ValidatorManager.getManager().suspendAllValidation(true); // don't validate when
			// migrating
			if (!ResourcesPlugin.getWorkspace().isTreeLocked())
				ResourcesPlugin.getWorkspace().run(getGlobalMigrator(), monitor);
		} catch (CoreException exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceIdentifier("ValidationMigrator::migrate"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		} finally {
			ValidatorManager.getManager().suspendAllValidation(wasSuspended);
		}
	}

	public void migrate(IProgressMonitor monitor, IProject project) {
		boolean wasSuspended = ValidatorManager.getManager().isProjectSuspended(project);
		try {
			ValidatorManager.getManager().suspendValidation(project, true); // Don't run validation
			// when migrating
			if (!ResourcesPlugin.getWorkspace().isTreeLocked())
				ResourcesPlugin.getWorkspace().run(getProjectMigrator(project), monitor);
		} catch (CoreException exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceIdentifier("ValidationMigrator::migrate"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		} finally {
			ValidatorManager.getManager().suspendValidation(project, wasSuspended);
		}
	}


	/**
	 * This method has package instead of private visibility because if it were private, then the
	 * compiler needs to access this method via a synthetic accessor method, and that can have
	 * performance consequences.
	 */
	void migrateValidator(IProgressMonitor monitor, Set vmds, IResource resource) {
		if (vmds == null) {
			return;
		}

		Iterator iterator = vmds.iterator();
		while (iterator.hasNext()) {
			ValidatorMetaData vmd = (ValidatorMetaData) iterator.next();
			migrateValidator(monitor, vmd, resource);
		}
	}

	/**
	 * If the Validator has registered a name change, update all existing validation markers with
	 * the new name.
	 */
	private void migrateValidator(IProgressMonitor monitor, ValidatorMetaData vmd, IResource resource) {
		ValidatorMetaData.MigrationMetaData mmd = vmd.getMigrationMetaData();
		if (mmd == null) {
			// no migration necessary
			return;
		}

		Set idList = mmd.getIds();
		if (idList == null) {
			// nothing to migrate
			return;
		}

		Iterator iterator = idList.iterator();
		while (iterator.hasNext()) {
			String[] ids = (String[]) iterator.next();
			if (ids.length != 2) {
				// log
				continue;
			}

			String from = ids[0];
			String to = ids[1];
			if ((from == null) || (to == null)) {
				// log
				continue;
			}

			try {
				TaskListUtility.updateOwner(from, to, resource);
			} catch (CoreException exc) {
				Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
				if (logger.isLoggingLevel(Level.SEVERE)) {
					LogEntry entry = ValidationPlugin.getLogEntry();
					entry.setSourceID("ValidationMigrator.migrateValidatorClass"); //$NON-NLS-1$
					entry.setTargetException(exc);
					logger.write(Level.SEVERE, entry);
				}
			}
		}
	}

	/**
	 * This method removes all orphaned validation markers (i.e., with no "owner" attribute set or
	 * when the validator isn't installed any more).
	 * 
	 * This method has package instead of private visibility because if it were private, then the
	 * compiler needs to access this method via a synthetic accessor method, and that can have
	 * performance consequences.
	 */
	void removeOrphanTasks(IProgressMonitor monitor, IResource resource) {
		// 1. Previous owner of "messageLimit" message was IReporter, but now is ValidatorManager.
		//    This will be taken care of by the "removeOrphanTasks" call, because
		// ValidatorManager.isInternalOwner
		//    will return false for IReporter.class.toString();
		try {
			IMarker[] orphanTasks = getOrphanTasks(monitor, resource);
			if (orphanTasks.length > 0) {
				monitor.subTask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_REMOVING));
				ResourcesPlugin.getWorkspace().deleteMarkers(orphanTasks);
				monitor.subTask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_REMOVINGDONE));
			}
		} catch (CoreException exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("ValidationMigrator.removeOrphanTasks"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}

	/**
	 * Return any markers whose owners do not exist (either the validator is not installed any more,
	 * or the marker was created incorrectly).
	 */
	private IMarker[] getOrphanTasks(IProgressMonitor monitor, IResource resource) throws CoreException {
		monitor.subTask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_LOOKING));
		try {
			if (resource == null) {
				return NO_MARKERS;
			}

			int orphanCount = 0;
			IMarker[] orphanList = null;
			IMarker[] markers = TaskListUtility.getValidationTasks(resource, SeverityEnum.ALL_MESSAGES);
			if (markers != null) {
				orphanList = new IMarker[markers.length];
				for (int i = 0; i < markers.length; i++) {
					IMarker marker = markers[i];

					Object owner = marker.getAttribute(VALIDATION_MARKER_OWNER);
					// If the owner is an existing validator or a validation framework class, then
					// it's
					// not an orphaned task.
					if ((owner == null) || !(owner instanceof String) || !((ValidationRegistryReader.getReader().isExistingValidator((String) owner) || ValidatorManager.getManager().isInternalOwner((String) owner)))) {
						orphanList[orphanCount++] = marker;
					}
				}
			}

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

			IMarker[] result = new IMarker[orphanCount];
			System.arraycopy(orphanList, 0, result, 0, orphanCount);
			return result;
		} finally {
			monitor.subTask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_LOOKINGDONE));
		}
	}

	/**
	 * This method has package instead of private visibility because if it were private, then the
	 * compiler needs to access this method via a synthetic accessor method, and that can have
	 * performance consequences.
	 */
	void migrateBuilder(IProgressMonitor monitor, IProject p) {
		try {
			ProjectConfiguration prjp = ConfigurationManager.getManager().getProjectConfiguration(p);
			String version = prjp.getVersion();
			if (!version.equals(VERSION4_03)) {
				// builder was migrated already. Only 4.03 needs to have its id migrated.
				return;
			}

			int newIdIndex = -1;
			int oldIdIndex = -1;
			if (p.exists() && p.isOpen()) {
				IProjectDescription description = p.getDescription();
				ICommand[] commands = description.getBuildSpec();
				for (int j = 0; j < commands.length; j++) {
					org.eclipse.core.resources.ICommand c = commands[j];
					String name = c.getBuilderName();
					if (name.equals("com.ibm.etools.j2ee.validationbuilder")) { //$NON-NLS-1$
						oldIdIndex = j;
					} else if (name.equals("org.eclipse.wst.validation.core.validationbuilder")) { //$NON-NLS-1$
						newIdIndex = j;
					}
				}

				if ((oldIdIndex > -1) && (newIdIndex > -1)) {
					// Don't need to add the new, just delete the old.
					ICommand[] newCommands = new ICommand[commands.length - 1];
					if (oldIdIndex == 0) {
						System.arraycopy(commands, 1, newCommands, 0, commands.length - 1);
					} else if (oldIdIndex == commands.length) {
						System.arraycopy(commands, 0, newCommands, 0, commands.length - 1);
					} else {
						System.arraycopy(commands, 0, newCommands, 0, oldIdIndex);
						System.arraycopy(commands, oldIdIndex + 1, newCommands, oldIdIndex, commands.length - oldIdIndex - 1);
					}
					description.setBuildSpec(newCommands);
				} else if (oldIdIndex > -1) {
					// Delete the old and add the new.
					ICommand command = description.newCommand();
					command.setBuilderName("org.eclipse.wst.validation.core.validationbuilder"); //$NON-NLS-1$
					commands[oldIdIndex] = command;
					description.setBuildSpec(commands);
				}

				p.setDescription(description, null);
			}
		} catch (CoreException exc) {
			// ignore. This is a temporary class anyways. Eventually everyone will move to a build
			// where the builder doesn't exist.
		} catch (InvocationTargetException exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceIdentifier("ValidationMigrator.migrateBuilder"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);

				if (exc.getTargetException() != null) {
					entry.setTargetException(exc.getTargetException());
					logger.write(Level.SEVERE, entry);
				}
			}
		}
	}
}