/*******************************************************************************
 * 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.core.internal.builder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.wst.sse.core.builder.IBuilderDelegate;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.SSECorePlugin;
import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;

public class StructuredDocumentBuilder extends IncrementalProjectBuilder implements IExecutableExtension {

	protected static final boolean _debugBuilder = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/builder")); //$NON-NLS-1$ //$NON-NLS-2$
	protected static final boolean _debugBuilderContentTypeDetection = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/builder/detection")); //$NON-NLS-1$ //$NON-NLS-2$
	protected static final boolean _debugBuilderPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/builder/time")); //$NON-NLS-1$ //$NON-NLS-2$
	private static final boolean performValidateEdit = false;

	private static boolean isGloballyEnabled = true;
	private static final String OFF = "off"; //$NON-NLS-1$
	static final boolean _debugResourceChangeListener = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/resourcechangehandling")); //$NON-NLS-1$ //$NON-NLS-2$

	protected static class ProjectChangeListener implements IResourceChangeListener, IResourceDeltaVisitor {
		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
		 */
		public void resourceChanged(IResourceChangeEvent event) {
			IResourceDelta delta = event.getDelta();
			if (delta.getResource() != null) {
				int resourceType = delta.getResource().getType();
				if (resourceType == IResource.PROJECT || resourceType == IResource.ROOT) {
					try {
						delta.accept(this);
					}
					catch (CoreException e) {
						Logger.logException("Exception managing buildspec list", e); //$NON-NLS-1$
					}
				}
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
		 */
		public boolean visit(IResourceDelta delta) throws CoreException {
			IResource resource = delta.getResource();
			if (resource != null) {
				if (resource.getType() == IResource.ROOT)
					return true;
				else if (resource.getType() == IResource.PROJECT) {
					if (delta.getKind() == IResourceDelta.ADDED) {
						if (_debugResourceChangeListener) {
							System.out.println("Project " + delta.getResource().getName() + " added to workspace and registering with SDMB");//$NON-NLS-2$//$NON-NLS-1$
						}
						add(new NullProgressMonitor(), (IProject) resource, null);
					}
					return false;
				}
			}
			return false;
		}
	}

	static {
		String build = System.getProperty(SSECorePlugin.STRUCTURED_BUILDER);
		isGloballyEnabled = (build == null || !build.equalsIgnoreCase(OFF));
	}

	/**
	 * Add the StructuredBuilder to the build spec of a single IProject
	 * 
	 * @param project -
	 *            the IProject to add to, when needed
	 */
	public static void add(IProgressMonitor monitor, IProject project, Object validateEditContext) {
		if (project == null || !project.isAccessible()) {
			return;
		}
		boolean isBuilderPresent = false;
		try {
			IFile descriptionFile = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
			if (descriptionFile.exists() && descriptionFile.isAccessible()) {
				IProjectDescription description = project.getDescription();
				ICommand[] commands = description.getBuildSpec();
				if (commands != null) {
					for (int i = 0; i < commands.length; i++) {
						String builderName = commands[i].getBuilderName();
						// builder name will be null if it has not been set
						if (builderName != null && builderName.equals(getBuilderId())) {
							isBuilderPresent = true;
							break;
						}
					}
				}
				if (!isBuilderPresent && !monitor.isCanceled()) {
					// validate for edit
					IStatus status = null;
					if (performValidateEdit) {
						ISchedulingRule validateEditRule = null;
						try {
							if (_debugBuilder) {
								System.out.println("Attempting validateEdit for " + descriptionFile.getFullPath().toString()); //$NON-NLS-1$
							}
							IFile[] validateFiles = new IFile[]{descriptionFile};
							IWorkspace workspace = descriptionFile.getWorkspace();
							validateEditRule = workspace.getRuleFactory().validateEditRule(validateFiles);
							Platform.getJobManager().beginRule(validateEditRule, monitor);
							status = workspace.validateEdit(validateFiles, null);
							if (_debugBuilder) {
								if (status.isOK()) {
									System.out.println("ValidateEdit completed for " + descriptionFile.getFullPath().toString()); //$NON-NLS-1$
								}
								else {
									System.out.println("ValidateEdit failed for " + descriptionFile.getFullPath().toString() + " " + status.getMessage()); //$NON-NLS-2$//$NON-NLS-1$
								}
							}
						}
						finally {
							if (validateEditRule != null) {
								Platform.getJobManager().endRule(validateEditRule);
							}
						}
					}
					if (status == null || status.isOK()) {
						// add the builder
						ICommand newCommand = description.newCommand();
						newCommand.setBuilderName(getBuilderId());
						ICommand[] newCommands = null;
						if (commands != null) {
							newCommands = new ICommand[commands.length + 1];
							System.arraycopy(commands, 0, newCommands, 0, commands.length);
							newCommands[commands.length] = newCommand;
						}
						else {
							newCommands = new ICommand[1];
							newCommands[0] = newCommand;
						}
						description.setBuildSpec(newCommands);
						/*
						 * This 'refresh' was added since unit tests were
						 * throwing exceptions about being out of sync. That
						 * may indicate a "deeper" problem such as needing to
						 * use scheduling rules, (although there don't appear
						 * to be examples of that) or something similar.
						 */
						// project.refreshLocal(IResource.DEPTH_ZERO,
						// subMonitorFor(monitor, 1,
						// IProgressMonitor.UNKNOWN));
						try {
							project.setDescription(description, subMonitorFor(monitor, 1, IProgressMonitor.UNKNOWN));
						}
						catch (CoreException e) {
							if (_debugBuilder) {
								if (performValidateEdit) {
									System.out.println("Description for project \"" + project.getName() + "\" could not be updated despite successful validateEdit"); //$NON-NLS-2$//$NON-NLS-1$
								}
								else {
									System.out.println("Description for project \"" + project.getName() + "\" could not be updated"); //$NON-NLS-2$//$NON-NLS-1$
								}
							}
							if (performValidateEdit) {
								Logger.log(Logger.WARNING, "Description for project \"" + project.getName() + "\" could not be updated despite successful validateEdit"); //$NON-NLS-2$//$NON-NLS-1$					
							}
							else {
								Logger.log(Logger.WARNING, "Description for project \"" + project.getName() + "\" could not be updated"); //$NON-NLS-2$//$NON-NLS-1$					
							}
						}
					}
				}
			}
			else {
				if (_debugBuilder) {
					System.out.println("Description for project \"" + project.getName() + "\" could not be updated"); //$NON-NLS-2$//$NON-NLS-1$
				}
				Logger.log(Logger.WARNING, "Description for project \"" + project.getName() + "\" could not be updated"); //$NON-NLS-2$//$NON-NLS-1$
			}
		}
		catch (Exception e) {
			// if we can't read the information, the project isn't open,
			// so it can't run auto-validate
			Logger.logException("Exception caught when adding Model Builder", e); //$NON-NLS-1$
		}
	}

	/**
	 * Adds the StructuredBuilder to every project in the Workspace
	 * 
	 * @param root
	 */
	public synchronized static void add(IProgressMonitor monitor, IWorkspaceRoot root, Object validateEditContext) {
		if (!isGloballyEnabled) {
			return;
		}
		IProject[] allProjects = root.getProjects();
		IProgressMonitor localMonitor = subMonitorFor(monitor, allProjects.length);
		localMonitor.beginTask(SSECorePlugin.getResourceString("%StructuredDocumentBuilder.0"), 1); //$NON-NLS-1$
		for (int i = 0; i < allProjects.length && !monitor.isCanceled(); i++) {
			add(localMonitor, allProjects[i], validateEditContext);
			localMonitor.worked(1);
		}
		localMonitor.done();
	}

	private static String getBuilderId() {
		return "org.eclipse.wst.sse.core.structuredbuilder"; //$NON-NLS-1$
	}

	public static IProgressMonitor monitorFor(IProgressMonitor monitor) {
		if (monitor == null)
			return new NullProgressMonitor();
		return monitor;
	}

	public static IProgressMonitor subMonitorFor(IProgressMonitor monitor, int ticks) {
		if (monitor == null)
			return new NullProgressMonitor();
		if (monitor instanceof NullProgressMonitor)
			return monitor;
		return new SubProgressMonitor(monitor, ticks);
	}

	public static IProgressMonitor subMonitorFor(IProgressMonitor monitor, int ticks, int style) {
		if (monitor == null)
			return new NullProgressMonitor();
		if (monitor instanceof NullProgressMonitor)
			return monitor;
		return new SubProgressMonitor(monitor, ticks, style);
	}

	protected List fActiveDelegates = null;
	private String fName = "Structured Document Builder"; //$NON-NLS-1$
	protected BuilderParticipantRegistryReader registry = null;

	private long time0;
	private IResourceChangeListener changeListener;

	/**
	 * 
	 */
	public StructuredDocumentBuilder() {
		super();
		if (isGloballyEnabled) {
			registry = new BuilderParticipantRegistryReader();
			fActiveDelegates = new ArrayList();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
	 *      java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
		IProject currentProject = getProject();
		// Currently, just use the Task Tags preference
		boolean locallyEnabled = isGloballyEnabled && SSECorePlugin.getDefault().getPluginPreferences().getBoolean(CommonModelPreferenceNames.TASK_TAG_ENABLE);
		if (!locallyEnabled || currentProject == null || !currentProject.isAccessible()) {
			if (_debugBuilderPerf || _debugBuilder) {
				System.out.println(getClass().getName() + " skipping build of " + currentProject.getName()); //$NON-NLS-1$
			}
			return new IProject[]{currentProject};
		}

		if (_debugBuilderPerf || _debugBuilder) {
			time0 = System.currentTimeMillis();
		}
		IResourceDelta delta = getDelta(currentProject);
		IProgressMonitor localMonitor = subMonitorFor(monitor, 1);
		localMonitor.beginTask(getDisplayName(), 1);

		if (!localMonitor.isCanceled()) {
			// check the kind of delta if one was given
			if (kind == FULL_BUILD || kind == CLEAN_BUILD || delta == null) {
				doFullBuild(kind, args, localMonitor, getProject());
			}
			else {
				doIncrementalBuild(kind, args, localMonitor);
			}
		}
		localMonitor.worked(1);
		shutdownDelegates();
		localMonitor.done();
		if (_debugBuilderPerf || _debugBuilder) {
			if (kind == FULL_BUILD || delta == null) {
				System.out.println(getClass().getName() + " finished FULL build of " + currentProject.getName() //$NON-NLS-1$
							+ " in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
			}
			else {
				System.out.println(getClass().getName() + " finished INCREMENTAL/CLEAN/AUTO build of " + currentProject.getName() //$NON-NLS-1$
							+ " in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		return new IProject[]{getProject()};
	}

	void build(int kind, Map args, IResource resource, IContentType[] types, IProgressMonitor monitor) {
		if (!monitor.isCanceled() && resource.getType() == IResource.FILE) {
			IBuilderDelegate[] delegates = null;
			List allDelegates = new ArrayList();
			for (int i = 0; i < types.length; i++) {
				IBuilderDelegate[] typeDelegates = registry.getBuilderDelegates(types[i].getId());
				if (typeDelegates != null && typeDelegates.length > 0) {
					allDelegates.addAll(Arrays.asList(typeDelegates));
				}
			}
			delegates = (IBuilderDelegate[]) allDelegates.toArray(new IBuilderDelegate[0]);
			for (int j = 0; delegates != null && j < delegates.length; j++) {
				if (kind != IncrementalProjectBuilder.CLEAN_BUILD) {
					monitor.subTask(getDisplayName() + " building " + resource.getFullPath()); //$NON-NLS-1$
				}
				try {
					if (!fActiveDelegates.contains(delegates[j]) && !monitor.isCanceled()) {
						delegates[j].startup(getProject(), kind, args);
						fActiveDelegates.add(delegates[j]);
					}
					delegates[j].build((IFile) resource, kind, args, subMonitorFor(monitor, 100));
				}
				catch (Exception e) {
					Logger.logException(e);
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected void clean(IProgressMonitor monitor) throws CoreException {
		if (_debugBuilderPerf || _debugBuilder) {
			time0 = System.currentTimeMillis();
		}
		super.clean(monitor);
		IProject currentProject = getProject();
		if (!isGloballyEnabled || currentProject == null || !currentProject.isAccessible()) {
			return;
		}
		doFullBuild(IncrementalProjectBuilder.CLEAN_BUILD, new HashMap(0), monitor, getProject());
		if (_debugBuilderPerf || _debugBuilder) {
			System.out.println(getClass().getName() + " finished CLEAN build of " + currentProject.getName() //$NON-NLS-1$
						+ " in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	IContentType[] detectContentTypes(IResource resource) {
		IContentType[] types = null;
		if (resource.getType() == IResource.FILE && resource.isAccessible()) {
			IContentDescription d = null;
			try {
				// optimized description lookup, might not succeed
				d = ((IFile) resource).getContentDescription();
				if (d != null) {
					types = new IContentType[]{d.getContentType()};
				}
			}
			catch (CoreException e) {
				// should not be possible given the accessible and file type
				// check above
			}
			if (types == null) {
				types = Platform.getContentTypeManager().findContentTypesFor(resource.getName());
			}
			if (_debugBuilderContentTypeDetection) {
				if (types.length > 0) {
					if (types.length > 1) {
						System.out.println(resource.getFullPath() + ": " + "multiple based on name (probably hierarchical)"); //$NON-NLS-1$ //$NON-NLS-2$
					}
					for (int i = 0; i < types.length; i++) {
						System.out.println(resource.getFullPath() + " matched: " + types[i].getId()); //$NON-NLS-1$
					}
				}
			}
		}
		return types;
	}

	/**
	 * Iterate through the list of resources and build each one
	 * 
	 * @param monitor
	 * @param resources
	 */
	protected void doFullBuild(int kind, Map args, IProgressMonitor monitor, IProject project) {
		if (_debugBuilder) {
			System.out.println(getClass().getName() + " building project " + project.getName()); //$NON-NLS-1$
		}

		final IProgressMonitor subMonitor = subMonitorFor(monitor, IProgressMonitor.UNKNOWN);
		final int localKind = kind;
		final Map localArgs = args;

		final IProgressMonitor visitorMonitor = monitor;
		IResourceVisitor internalBuilder = new IResourceVisitor() {
			public boolean visit(IResource resource) throws CoreException {
				if (resource.getType() == IResource.FILE) {
					// for any supported file type, record the resource
					IContentType[] contentTypes = detectContentTypes(resource);
					if (contentTypes != null) {
						build(localKind, localArgs, resource, contentTypes, subMonitor);
						visitorMonitor.worked(1);
					}
					return false;
				}
				else {
					return true;
				}
			}

		};
		try {
			project.accept(internalBuilder);
		}
		catch (CoreException e) {
			Logger.logException(e);
		}
	}

	/**
	 * 
	 */
	protected void doIncrementalBuild(int kind, Map args, IProgressMonitor monitor) {
		IResourceDelta projectDelta = getDelta(getProject());
		if (projectDelta == null) {
			throw new IllegalArgumentException("delta is null, should do a full build"); //$NON-NLS-1$
		}
		if (_debugBuilder) {
			if (projectDelta != null && projectDelta.getResource() != null) {
				System.out.println(getClass().getName() + " building " + projectDelta.getResource().getFullPath()); //$NON-NLS-1$
			}
			else {
				System.out.println(getClass().getName() + " building project " + getProject().getName()); //$NON-NLS-1$
			}
		}

		final Map localArgs = args;
		final int localKind = kind;
		final IProgressMonitor localMonitor = subMonitorFor(monitor, IProgressMonitor.UNKNOWN, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
		IResourceDeltaVisitor participantVisitor = new IResourceDeltaVisitor() {
			public boolean visit(IResourceDelta delta) throws CoreException {
				if (!localMonitor.isCanceled() && delta.getResource().getType() == IResource.FILE) {
					IContentType[] contentTypes = detectContentTypes(delta.getResource());
					if (contentTypes != null)
						build(localKind, localArgs, delta.getResource(), contentTypes, localMonitor);
				}
				return delta.getAffectedChildren().length > 0;
			}
		};
		try {
			projectDelta.accept(participantVisitor);
		}
		catch (CoreException e) {
			Logger.logException(e);
		}
		monitor.worked(1);
	}

	private String getDisplayName() {
		return fName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
	 *      java.lang.String, java.lang.Object)
	 */
	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
		if (config != null) {
			fName = config.getDeclaringExtension().getLabel();
		}
	}

	/**
	 * 
	 */
	private void shutdownDelegates() {
		for (int j = 0; j < fActiveDelegates.size(); j++) {
			try {
				((IBuilderDelegate) fActiveDelegates.get(j)).shutdown(getProject());
			}
			catch (Exception e) {
				Logger.logException(e);
			}
		}
		fActiveDelegates = new ArrayList(1);
	}

	// make private if ever used again
	void doTaskTagProcessing() {
		// Must make sure the builder is registered for projects which may
		// have been created before this plugin was activated.
		Job adder = new WorkspaceJob(SSECorePlugin.getResourceString("%ModelPlugin.0")) { //$NON-NLS-1$
			public IStatus runInWorkspace(IProgressMonitor monitor) {
				add(monitor, ResourcesPlugin.getWorkspace().getRoot(), null);
				return Status.OK_STATUS;
			}
		};
		adder.setSystem(true);
		// use SHORT, since once executing, this job should be quick
		adder.setPriority(Job.SHORT);
		// since we have potential to change several .project files,
		// we should wait until we can get exclusive access to
		// whole workspace.
		// TODO: future re-design should not require this.
		adder.setRule(ResourcesPlugin.getWorkspace().getRoot());
		adder.schedule();

		// Register the ProjectChangeListener so that it can add the
		// builder
		// to projects as needed
		changeListener = new ProjectChangeListener();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(changeListener, IResourceChangeEvent.PRE_BUILD);
	}

	/**
	 * Only for use by ModelPlugin class
	 */
	public static void shutdown() {
	}

	/**
	 * Only for use by ModelPlugin class
	 */
	public static void startup() {
		// TODO:disabled for now
	}
}
