/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     Andrey Loskutov <loskutov@gmx.de> - generified interface, bug 462760
 *******************************************************************************/
package org.eclipse.ui.actions;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
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.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StatusUtil;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import org.eclipse.ui.progress.IProgressConstants2;

/**
 * The abstract superclass for actions which invoke commands implemented in
 * org.eclipse.core.* on a set of selected resources.
 *
 * It iterates over all selected resources; errors are collected and displayed
 * to the user via a problems dialog at the end of the operation. User requests
 * to cancel the operation are passed along to the core.
 * <p>
 * Subclasses must implement the following methods:
 * <ul>
 * <li><code>invokeOperation</code> - to perform the operation on one of the
 * selected resources</li>
 * <li><code>getOperationMessage</code> - to furnish a title for the progress
 * dialog</li>
 * </ul>
 * </p>
 * <p>
 * Subclasses may override the following methods:
 * <ul>
 * <li><code>shouldPerformResourcePruning</code> - reimplement to turn off</li>
 * <li><code>updateSelection</code> - extend to refine enablement criteria</li>
 * <li><code>getProblemsTitle</code> - reimplement to furnish a title for the
 * problems dialog</li>
 * <li><code>getProblemsMessage</code> - reimplement to furnish a message for
 * the problems dialog</li>
 * <li><code>run</code> - extend to </li>
 * </ul>
 * </p>
 */
public abstract class WorkspaceAction extends SelectionListenerAction {
	/**
	 * The shell in which to show the progress and problems dialog.
	 */
	private final IShellProvider shellProvider;

	/**
	 * Creates a new action with the given text.
	 *
	 * @param shell
	 *            the shell (for the modal progress dialog and error messages)
	 * @param text
	 *            the string used as the text for the action, or
	 *            <code>null</code> if there is no text
	 * @deprecated See {@link #WorkspaceAction(IShellProvider, String)}
	 */
	@Deprecated
	protected WorkspaceAction(final Shell shell, String text) {
		super(text);
		Assert.isNotNull(shell);
		shellProvider = () -> shell;
	}

	/**
	 * Creates a new action with the given text.
	 *
	 * @param provider
	 *            the shell provider (for the modal progress dialog and error
	 *            messages)
	 * @param text
	 *            the string used as the text for the action, or
	 *            <code>null</code> if there is no text
	 * @since 3.4
	 */
	protected WorkspaceAction(IShellProvider provider, String text) {
		super(text);
		Assert.isNotNull(provider);
		shellProvider = provider;
	}

	/**
	 * Opens an error dialog to display the given message.
	 * <p>
	 * Note that this method must be called from UI thread.
	 * </p>
	 *
	 * @param message
	 *            the message
	 */
	void displayError(String message) {
		if (message == null) {
			message = IDEWorkbenchMessages.WorkbenchAction_internalError;
		}
		MessageDialog.openError(shellProvider.getShell(), getProblemsTitle(), message);
	}

	/**
	 * Runs <code>invokeOperation</code> on each of the selected resources,
	 * reporting progress and fielding cancel requests from the given progress
	 * monitor.
	 * <p>
	 * Note that if an action is running in the background, the same action
	 * instance can be executed multiple times concurrently. This method must
	 * not access or modify any mutable state on action class.
	 *
	 * @param monitor
	 *            a progress monitor
	 * @return The result of the execution
	 */
	final IStatus execute(List<? extends IResource> resources, IProgressMonitor mon) {
		MultiStatus errors = null;
		// 1FTIMQN: ITPCORE:WIN - clients required to do too much iteration work
		if (shouldPerformResourcePruning()) {
			resources = pruneResources(resources);
		}
		SubMonitor subMonitor = SubMonitor.convert(mon, resources.size());
		// Fix for bug 31768 - Don't provide a task name in beginTask
		// as it will be appended to each subTask message. Need to
		// call setTaskName as its the only was to assure the task name is
		// set in the monitor (see bug 31824)
		subMonitor.setTaskName(getOperationMessage());
		for (IResource resource : resources) {
			try {
				invokeOperation(resource, subMonitor.split(1));
			} catch (CoreException e) {
				errors = recordError(errors, e);
			}
		}
		return errors == null ? Status.OK_STATUS : errors;
	}

	/**
	 * Returns the string to display for this action's operation.
	 * <p>
	 * Note that this hook method is invoked in a non-UI thread.
	 * </p>
	 * <p>
	 * Subclasses must implement this method.
	 * </p>
	 *
	 * @return the message
	 *
	 * @since 3.1
	 */
	protected abstract String getOperationMessage();

	/**
	 * Returns the string to display for this action's problems dialog.
	 * <p>
	 * The <code>WorkspaceAction</code> implementation of this method returns
	 * a vague message (localized counterpart of something like "The following
	 * problems occurred."). Subclasses may reimplement to provide something
	 * more suited to the particular action.
	 * </p>
	 *
	 * @return the problems message
	 *
	 * @since 3.1
	 */
	protected String getProblemsMessage() {
		return IDEWorkbenchMessages.WorkbenchAction_problemsMessage;
	}

	/**
	 * Returns the title for this action's problems dialog.
	 * <p>
	 * The <code>WorkspaceAction</code> implementation of this method returns
	 * a generic title (localized counterpart of "Problems"). Subclasses may
	 * reimplement to provide something more suited to the particular action.
	 * </p>
	 *
	 * @return the problems dialog title
	 *
	 * @since 3.1
	 */
	protected String getProblemsTitle() {
		return IDEWorkbenchMessages.WorkspaceAction_problemsTitle;
	}

	/**
	 * Returns the shell for this action. This shell is used for the modal
	 * progress and error dialogs.
	 *
	 * @return the shell
	 */
	Shell getShell() {
		return shellProvider.getShell();
	}

	/**
	 * Performs this action's operation on each of the selected resources,
	 * reporting progress to, and fielding cancel requests from, the given
	 * progress monitor.
	 * <p>
	 * Note that this method is invoked in a non-UI thread.
	 * </p>
	 * <p>
	 * Subclasses must implement this method.
	 * <p>
	 * @deprecated Since 3.3, subclasses should instead implement the method
	 * {@link #createOperation(IStatus[])} and provide an empty implementation
	 * for this method.
	 * </p>
	 *
	 * @param resource
	 *            one of the selected resources
	 * @param monitor
	 *            a progress monitor
	 * @exception CoreException
	 *                if the operation fails
	 *
	 * @since 3.1
	 */
	@Deprecated
	protected void invokeOperation(IResource resource, IProgressMonitor monitor) throws CoreException {

	}

	/**
	 * Returns whether the given resource is a descendent of any of the
	 * resources in the given list.
	 *
	 * @param resources
	 *            the list of resources (element type: <code>IResource</code>)
	 * @param child
	 *            the resource to check
	 * @return <code>true</code> if <code>child</code> is a descendent of
	 *         any of the elements of <code>resources</code>
	 */
	boolean isDescendent(List<IResource> resources, IResource child) {
		IResource parent = child.getParent();
		return parent != null && (resources.contains(parent) || isDescendent(resources, parent));
	}

	/**
	 * Performs pruning on the given list of resources, as described in
	 * <code>shouldPerformResourcePruning</code>.
	 *
	 * @param resourceCollection
	 *            the list of resources (element type: <code>IResource</code>)
	 * @return the list of resources (element type: <code>IResource</code>)
	 *         after pruning.
	 * @see #shouldPerformResourcePruning
	 */
	List<IResource> pruneResources(List<? extends IResource> resourceCollection) {
		List<IResource> prunedList = new ArrayList<>(resourceCollection);
		Iterator<IResource> elementsEnum = prunedList.iterator();
		while (elementsEnum.hasNext()) {
			IResource currentResource = elementsEnum.next();
			if (isDescendent(prunedList, currentResource)) {
				elementsEnum.remove(); // Removes currentResource
			}
		}
		return prunedList;
	}

	/**
	 * Records the core exception to be displayed to the user once the action is
	 * finished.
	 *
	 * @param error
	 *            a <code>CoreException</code>
	 */
	MultiStatus recordError(MultiStatus errors, CoreException error) {
		if (errors == null) {
			errors = new MultiStatus(IDEWorkbenchPlugin.IDE_WORKBENCH, IStatus.ERROR, getProblemsMessage(), null);
		}
		errors.merge(error.getStatus());
		return errors;
	}

	/**
	 * The <code>CoreWrapperAction</code> implementation of this
	 * <code>IAction</code> method uses a <code>ProgressMonitorDialog</code>
	 * to run the operation. The operation calls <code>execute</code> (which,
	 * in turn, calls <code>invokeOperation</code>). Afterwards, any
	 * <code>CoreException</code>s encountered while running the operation
	 * are reported to the user via a problems dialog.
	 * <p>
	 * Subclasses may extend this method.
	 * </p>
	 */
	@Override
	public void run() {
		IStatus[] errorStatus = new IStatus[1];
		try {
			new ProgressMonitorJobsDialog(shellProvider.getShell()).run(true, true, createOperation(errorStatus));
		} catch (InterruptedException e) {
			return;
		} catch (InvocationTargetException e) {
			// we catch ExecutionException in the created operation, but unexpected runtime
			// exceptions or errors may still occur
			String msg = NLS.bind(
					IDEWorkbenchMessages.WorkspaceAction_logTitle, getClass()
							.getName(), e.getTargetException());
			IDEWorkbenchPlugin.log(msg, StatusUtil.newStatus(IStatus.ERROR, msg, e.getTargetException()));
			displayError(e.getTargetException().getMessage());
		}
		// If errors occurred, open an Error dialog & build a multi status error
		// for it
		if (errorStatus[0] != null && !errorStatus[0].isOK()) {
			// no special message
			ErrorDialog.openError(shellProvider.getShell(), getProblemsTitle(), null, errorStatus[0]);
		}
	}

	/**
	 * Returns whether this action should attempt to optimize the resources
	 * being operated on. This kind of pruning makes sense when the operation
	 * has depth infinity semantics (when the operation is applied explicitly to
	 * a resource then it is also applied implicitly to all the resource's
	 * descendents).
	 * <p>
	 * The <code>WorkspaceAction</code> implementation of this method returns
	 * <code>true</code>. Subclasses should reimplement to return
	 * <code>false</code> if pruning is not required.
	 * </p>
	 *
	 * @return <code>true</code> if pruning should be performed, and
	 *         <code>false</code> if pruning is not desired
	 *
	 * @since 3.1
	 */
	protected boolean shouldPerformResourcePruning() {
		return true;
	}

	/**
	 * The <code>WorkspaceAction</code> implementation of this
	 * <code>SelectionListenerAction</code> method ensures that this action is
	 * disabled if any of the selected resources are inaccessible. Subclasses
	 * may extend to react to selection changes; however, if the super method
	 * returns <code>false</code>, the overriding method should also return
	 * <code>false</code>.
	 */
	@Override
	protected boolean updateSelection(IStructuredSelection selection) {
		if (!super.updateSelection(selection) || selection.isEmpty()) {
			return false;
		}
		for (IResource r : getSelectedResources()) {
			if (!r.isAccessible()) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Returns the elements that the action is to be performed on. By default
	 * return the selected resources.
	 * <p>
	 * Subclasses may override this method.
	 *
	 * @return list of resource elements (element type: <code>IResource</code>)
	 */
	protected List<? extends IResource> getActionResources() {
		return getSelectedResources();
	}

	/**
	 * Run the action in the background rather than with the progress dialog.
	 *
	 * @param rule
	 *            The rule to apply to the background job or <code>null</code>
	 *            if there isn't one.
	 */
	public void runInBackground(ISchedulingRule rule) {
		runInBackground(rule, (Object[]) null);
	}

	/**
	 * Run the action in the background rather than with the progress dialog.
	 *
	 * @param rule
	 *            The rule to apply to the background job or <code>null</code>
	 *            if there isn't one.
	 * @param jobFamily
	 *            a single family that the job should belong to or
	 *            <code>null</code> if none.
	 *
	 * @since 3.1
	 */
	public void runInBackground(ISchedulingRule rule, Object jobFamily) {
		if (jobFamily == null) {
			runInBackground(rule, (Object[]) null);
		} else {
			runInBackground(rule, new Object[] { jobFamily });
		}
	}

	/**
	 * Run the action in the background rather than with the progress dialog.
	 *
	 * @param rule
	 *            The rule to apply to the background job or <code>null</code>
	 *            if there isn't one.
	 * @param jobFamilies
	 *            the families the job should belong to or <code>null</code>
	 *            if none.
	 *
	 * @since 3.1
	 */
	public void runInBackground(ISchedulingRule rule, final Object[] jobFamilies) {
		// obtain a copy of the selected resources before the job is forked
		final List<IResource> resources = new ArrayList<>(getActionResources());
		Job job = new WorkspaceJob(removeMnemonics(getText())) {

			@Override
			public boolean belongsTo(Object family) {
				if (jobFamilies == null || family == null) {
					return false;
				}
				for (Object jobFamily : jobFamilies) {
					if (family.equals(jobFamily)) {
						return true;
					}
				}
				return false;
			}

			@Override
			public IStatus runInWorkspace(IProgressMonitor monitor) {
				return WorkspaceAction.this.execute(resources, monitor);
			}
		};
		if (rule != null) {
			job.setRule(rule);
		}
		if (job.belongsTo(ResourcesPlugin.FAMILY_MANUAL_BUILD)) {
			job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE);
		}
		job.setUser(true);
		job.schedule();
	}

	/**
	 * Returns the operation to perform when this action runs. The returned
	 * operation must be an {@link IRunnableWithProgress} that will perform the
	 * action's work. The default implementation returns an operation that will
	 * iterate over the selected resources and call
	 * {@link #invokeOperation(IResource, IProgressMonitor)} for each resource.
	 * Subclasses must either implement
	 * {@link #invokeOperation(IResource, IProgressMonitor)} or override this
	 * method to provide a different operation. Subclasses typically override
	 * this method when an undoable operation is to be provided.
	 *
	 * @param errorStatus
	 *            an array of error status objects to which the result of
	 *            running the operation should be added.
	 *
	 * @return the operation to perform when this action runs.
	 * @since 3.3
	 */
	protected IRunnableWithProgress createOperation(final IStatus[] errorStatus) {
		return new WorkspaceModifyOperation() {
			@Override
			public void execute(IProgressMonitor monitor) {
				errorStatus[0] = WorkspaceAction.this.execute(getActionResources(), monitor);
			}
		};
	}

}
