/*******************************************************************************
 * Copyright (c) 2006, 2009 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
 * Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 94808 [Change Sets] "&" not showing up in dropdown menu
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.mappings;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.widgets.Control;
import org.eclipse.team.core.diff.*;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.internal.ccvs.core.mapping.ChangeSetModelProvider;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.core.subscribers.*;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.internal.ui.mapping.ResourceModelActionProvider;
import org.eclipse.team.internal.ui.mapping.ResourceModelTraversalCalculator;
import org.eclipse.team.internal.ui.synchronize.*;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.BaseSelectionListenerAction;
import org.eclipse.ui.navigator.INavigatorContentExtension;
import org.eclipse.ui.navigator.INavigatorContentService;

public class ChangeSetActionProvider extends ResourceModelActionProvider {

	/**
	 * Menu group that can be added to the context menu
	 */
	public final static String CHANGE_SET_GROUP = "changeSetActions"; //$NON-NLS-1$

	// Constants for persisting sorting options
	private static final String P_LAST_COMMENTSORT = TeamUIPlugin.ID + ".P_LAST_COMMENT_SORT"; //$NON-NLS-1$

	private MenuManager sortByComment;
	private MenuManager addToChangeSet;
	private CreateChangeSetAction createChangeSet;
	private EditChangeSetAction editChangeSet;
	private RemoveChangeSetAction removeChangeSet;
	private MakeDefaultChangeSetAction makeDefault;
	private OpenChangeSetAction openCommitSet;

	private class CreateChangeSetAction extends ModelParticipantAction {

		public CreateChangeSetAction(ISynchronizePageConfiguration configuration) {
			super(TeamUIMessages.ChangeLogModelProvider_0, configuration);
		}

		public void run() {
			final IDiff[] diffs = getLocalChanges(getStructuredSelection());
			syncExec(new Runnable() {
				public void run() {
					createChangeSet(diffs);
				}
			});
		}

		/* package */void createChangeSet(IDiff[] diffs) {
            ActiveChangeSet set =  getChangeSetCapability().createChangeSet(getConfiguration(), diffs);
			if (set != null) {
				getActiveChangeSetManager().add(set);
			}
		}

		protected boolean isEnabledForSelection(IStructuredSelection selection) {
			return isContentProviderEnabled()
					&& containsOnlyLocalChanges(selection);
		}
	}

	/**
	 * Escape a string so it can be used as an action text without '&'
	 * being interpreted as a mnemonic. Specifically, turn each '&' into '&&'.
	 */
	/* package */static String escapeActionText(String x) {
		// Loosely based on org.eclipse.jface.action.LegacyActionTools#removeMnemonics
		int ampersandIndex = x.indexOf('&');
		if (ampersandIndex == -1)
			return x;

		int len = x.length();
		StringBuffer sb = new StringBuffer(2 * len + 1);
		int doneIndex = 0;
		while (ampersandIndex != -1) {
			sb.append(x.substring(doneIndex, ampersandIndex));
			sb.append("&&"); //$NON-NLS-1$
			doneIndex = ampersandIndex + 1;
			ampersandIndex = x.indexOf('&', doneIndex);
		}
		if (doneIndex < len)
			sb.append(x.substring(doneIndex, len));
		return sb.toString();
	}

	private class AddToChangeSetAction extends ModelParticipantAction {

		private final ActiveChangeSet set;

        public AddToChangeSetAction(ISynchronizePageConfiguration configuration, ActiveChangeSet set, ISelection selection) {
            super(set == null ? TeamUIMessages.ChangeSetActionGroup_2 : escapeActionText(set.getTitle()), configuration); 
			this.set = set;
			selectionChanged(selection);
		}

		public void run() {
			IDiff[] diffArray = getLocalChanges(getStructuredSelection());
			if (set != null) {
				set.add(diffArray);
			} else {
				ChangeSet[] sets = getActiveChangeSetManager().getSets();
				IResource[] resources = getResources(diffArray);
				for (int i = 0; i < sets.length; i++) {
					ActiveChangeSet activeSet = (ActiveChangeSet) sets[i];
					activeSet.remove(resources);
				}
			}
		}

		protected boolean isEnabledForSelection(IStructuredSelection selection) {
			return isContentProviderEnabled()
					&& containsOnlyLocalChanges(selection);
		}
	}

	private abstract class ChangeSetAction extends BaseSelectionListenerAction {

        public ChangeSetAction(String title, ISynchronizePageConfiguration configuration) {
			super(title);
		}

        /* (non-Javadoc)
         * @see org.eclipse.ui.actions.BaseSelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection)
		 */
		protected boolean updateSelection(IStructuredSelection selection) {
			return getSelectedSet() != null;
		}

		protected ActiveChangeSet getSelectedSet() {
			IStructuredSelection selection = getStructuredSelection();
			if (selection.size() == 1) {
				Object first = selection.getFirstElement();
				if (first instanceof ActiveChangeSet) {
					ActiveChangeSet activeChangeSet = (ActiveChangeSet) first;
					if (activeChangeSet.isUserCreated())
						return activeChangeSet;
				}
			}
			return null;
		}
	}

	private class EditChangeSetAction extends ChangeSetAction {

		public EditChangeSetAction(ISynchronizePageConfiguration configuration) {
			super(TeamUIMessages.ChangeLogModelProvider_6, configuration);
		}

		public void run() {
			ActiveChangeSet set = getSelectedSet();
            if (set == null) return;
            getChangeSetCapability().editChangeSet(internalGetSynchronizePageConfiguration(), set);
		}
	}

	private class RemoveChangeSetAction extends ModelParticipantAction {

		public RemoveChangeSetAction(ISynchronizePageConfiguration configuration) {
			super(TeamUIMessages.ChangeLogModelProvider_7, configuration);
		}

		public void run() {
			IDiff[] diffArray = getLocalChanges(getStructuredSelection());
			ChangeSet[] sets = getActiveChangeSetManager().getSets();
			IResource[] resources = getResources(diffArray);
			for (int i = 0; i < sets.length; i++) {
				ActiveChangeSet activeSet = (ActiveChangeSet) sets[i];
				activeSet.remove(resources);
			}
		}

		protected boolean isEnabledForSelection(IStructuredSelection selection) {
			return isContentProviderEnabled()
					&& containsOnlyLocalChanges(selection);
		}
	}

	private class MakeDefaultChangeSetAction extends ChangeSetAction {
        public MakeDefaultChangeSetAction(ISynchronizePageConfiguration configuration) {
			super(TeamUIMessages.ChangeLogModelProvider_9, configuration);
		}

		public void run() {
			ActiveChangeSet set = getSelectedSet();
            if (set == null) return;
			getActiveChangeSetManager().makeDefault(set);
		}
	}

	/* *****************************************************************************
	 * Action that allows changing the model providers sort order.
	 */
	private class ToggleSortOrderAction extends Action {
		private int criteria;

		protected ToggleSortOrderAction(String name, int criteria) {
			super(name, IAction.AS_RADIO_BUTTON);
			this.criteria = criteria;
			update();
		}

		public void run() {
			int sortCriteria = getSortCriteria(internalGetSynchronizePageConfiguration());
			if (isChecked() && sortCriteria != criteria) {
			    setSortCriteria(internalGetSynchronizePageConfiguration(), criteria);
				update();
				((SynchronizePageConfiguration)internalGetSynchronizePageConfiguration()).getPage().getViewer().refresh();
			}
		}

		public void update() {
			setChecked(criteria == getSortCriteria(internalGetSynchronizePageConfiguration()));
		}
	}

    public static int getSortCriteria(ISynchronizePageConfiguration configuration) {
		int sortCriteria = ChangeSetSorter.DATE;
		if (configuration != null) {
			Object o = configuration.getProperty(P_LAST_COMMENTSORT);
			if (o instanceof Integer) {
				Integer wrapper = (Integer) o;
				sortCriteria = wrapper.intValue();
			} else {
				try {
					IDialogSettings pageSettings = configuration.getSite().getPageSettings();
					if (pageSettings != null) {
						sortCriteria = pageSettings.getInt(P_LAST_COMMENTSORT);
					}
				} catch (NumberFormatException e) {
					// ignore and use the defaults.
				}
			}
		}
		switch (sortCriteria) {
		case ChangeSetSorter.COMMENT:
		case ChangeSetSorter.DATE:
		case ChangeSetSorter.USER:
			break;
		default:
			sortCriteria = ChangeSetSorter.DATE;
			break;
		}
		return sortCriteria;
	}

	public static void setSortCriteria(ISynchronizePageConfiguration configuration, int criteria) {
		configuration.setProperty(P_LAST_COMMENTSORT, new Integer(criteria));
		IDialogSettings pageSettings = configuration.getSite().getPageSettings();
		if (pageSettings != null) {
			pageSettings.put(P_LAST_COMMENTSORT, criteria);
		}
	}

	public ChangeSetActionProvider() {
		super();
	}

	protected void initialize() {
		super.initialize();
		if (getChangeSetCapability().supportsCheckedInChangeSets()) {
			sortByComment = new MenuManager(TeamUIMessages.ChangeLogModelProvider_0a);	 
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_1a, ChangeSetSorter.COMMENT)); 
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_2a, ChangeSetSorter.DATE)); 
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_3a, ChangeSetSorter.USER));
			openCommitSet = new OpenChangeSetAction(getSynchronizePageConfiguration());
		}
		if (getChangeSetCapability().supportsActiveChangeSets()) {
			createChangeSet = new CreateChangeSetAction(
					getSynchronizePageConfiguration());
			editChangeSet = new EditChangeSetAction(
					getSynchronizePageConfiguration());
			makeDefault = new MakeDefaultChangeSetAction(
					getSynchronizePageConfiguration());
			removeChangeSet = new RemoveChangeSetAction(
					getSynchronizePageConfiguration());
		}
	}

	protected ActiveChangeSet getSelectedActiveChangeSet(
			IStructuredSelection selection) {
		if (selection.size() == 1) {
			Object first = selection.getFirstElement();
			if (first instanceof ActiveChangeSet) {
				ActiveChangeSet activeChangeSet = (ActiveChangeSet) first;
				if (activeChangeSet.isUserCreated())
					return activeChangeSet;
			}
		}
		return null;
	}

	private IResource[] getResources(IDiff[] diffArray) {
		List result = new ArrayList();
		for (int i = 0; i < diffArray.length; i++) {
			IDiff diff = diffArray[i];
			IResource resource = ResourceDiffTree.getResourceFor(diff);
			if (resource != null) {
				result.add(resource);
			}
		}
		return (IResource[]) result.toArray(new IResource[result.size()]);
	}

	public void fillContextMenu(IMenuManager menu) {
		if (isContentProviderEnabled()) {
			super.fillContextMenu(menu);
			if (getChangeSetCapability().enableCheckedInChangeSetsFor(
					getSynchronizePageConfiguration())) {
				appendToGroup(menu, "file-bottom", //$NON-NLS-1$
						openCommitSet);
				appendToGroup(menu, ISynchronizePageConfiguration.SORT_GROUP,
						sortByComment);
			}
			IStructuredSelection selection = (IStructuredSelection) getContext()
					.getSelection();
			if (getChangeSetCapability().enableActiveChangeSetsFor(
					getSynchronizePageConfiguration())
					&& containsOnlyLocalChanges(selection)) {

				if (containsOnlyUnassignedChanges(selection)) {
					// only local unassigned changes
					addToChangeSet = new MenuManager(
							TeamUIMessages.ChangeLogModelProvider_13);
					appendToGroup(menu, CHANGE_SET_GROUP, addToChangeSet);
				} else {
					addToChangeSet = new MenuManager(
							TeamUIMessages.ChangeLogModelProvider_12);
					appendToGroup(menu, CHANGE_SET_GROUP, addToChangeSet);
					appendToGroup(menu, CHANGE_SET_GROUP, removeChangeSet);
				}

				addChangeSets(addToChangeSet);

				if (getSelectedActiveChangeSet(selection) == null)
					return;
				appendToGroup(menu, CHANGE_SET_GROUP, editChangeSet);
				appendToGroup(menu, CHANGE_SET_GROUP, makeDefault);
			}
		}
	}
	
	protected void addChangeSets(IMenuManager manager) {
		ChangeSet[] sets = getActiveChangeSetManager().getSets();
		Arrays.sort(sets, new ChangeSetComparator());
		ISelection selection = getContext().getSelection();
		createChangeSet.selectionChanged(selection);
		manager.add(createChangeSet);
		manager.add(new Separator());
		for (int i = 0; i < sets.length; i++) {
			ActiveChangeSet set = (ActiveChangeSet) sets[i];
			AddToChangeSetAction action = new AddToChangeSetAction(
					getSynchronizePageConfiguration(), set, selection);
			manager.add(action);
		}
		manager.add(new Separator());
	}

	public void dispose() {
		if (addToChangeSet != null) {
			addToChangeSet.dispose();
			addToChangeSet.removeAll();
		}
		if (sortByComment != null) {
			sortByComment.dispose();
			sortByComment.removeAll();
		}
		super.dispose();
	}

	private boolean appendToGroup(IContributionManager manager, String groupId, IContributionItem item) {
		if (manager == null || item == null) return false;
		IContributionItem group = manager.find(groupId);
		if (group != null) {
			manager.appendToGroup(group.getId(), item);
			return true;
		}
		return false;
	}

	private boolean appendToGroup(IContributionManager manager, String groupId, IAction action) {
		if (manager == null || action == null) return false;
		IContributionItem group = manager.find(groupId);
		if (group != null) {
			manager.appendToGroup(group.getId(), action);
			// registerActionWithWorkbench(action);
			return true;
		}
		return false;
	}

	public ChangeSetCapability getChangeSetCapability() {
        ISynchronizeParticipant participant = getSynchronizePageConfiguration().getParticipant();
		if (participant instanceof IChangeSetProvider) {
			IChangeSetProvider provider = (IChangeSetProvider) participant;
			return provider.getChangeSetCapability();
		}
		return null;
	}

	/* package */void syncExec(final Runnable runnable) {
		final Control ctrl = getSynchronizePageConfiguration().getPage().getViewer().getControl();
		Utils.syncExec(runnable, ctrl);
	}

	/* package */ActiveChangeSetManager getActiveChangeSetManager() {
		return CVSUIPlugin.getPlugin().getChangeSetManager();
	}

	public IDiff[] getLocalChanges(IStructuredSelection selection) {
		if (selection instanceof ITreeSelection) {
			ITreeSelection ts = (ITreeSelection) selection;
			TreePath[] paths = ts.getPaths();
			List result = new ArrayList();
			for (int i = 0; i < paths.length; i++) {
				TreePath path = paths[i];
				IDiff[] diffs = getLocalChanges(path);
				for (int j = 0; j < diffs.length; j++) {
					IDiff diff = diffs[j];
					result.add(diff);
				}
			}
			return (IDiff[]) result.toArray(new IDiff[result.size()]);
		}
		return new IDiff[0];
	}

	private IDiff[] getLocalChanges(TreePath path) {
		IResourceDiffTree tree = getDiffTree(path);
		if (path.getSegmentCount() == 1 && path.getLastSegment() instanceof IDiffTree) {
			return ((ResourceDiffTree) tree).getDiffs();
		}
		ResourceTraversal[] traversals = getTraversals(path.getLastSegment());
		return tree.getDiffs(traversals);
	}

	private IResourceDiffTree getDiffTree(TreePath path) {
		return getContentProvider().getDiffTree(path);
	}
	
	
	private boolean containsOnlyUnassignedChanges(IStructuredSelection selection) {
		IDiff[] diffArray = getLocalChanges(selection);
		ChangeSet[] activeChangeSets = getActiveChangeSetManager().getSets();
		IResource[] resources = getResources(diffArray);
		for (int i = 0; i < activeChangeSets.length; i++) {
			for (int j = 0; j < resources.length; j++) {
				if (activeChangeSets[i].contains(resources[j]))
					return false;
			}
		}
		return true;
	}

	public boolean containsOnlyLocalChanges(IStructuredSelection selection) {
		if (selection instanceof ITreeSelection) {
			ITreeSelection ts = (ITreeSelection) selection;
			TreePath[] paths = ts.getPaths();
			for (int i = 0; i < paths.length; i++) {
				TreePath path = paths[i];
				if (!containsOnlyLocalChanges(path)) {
					return false;
				}
			}
		}
		return true;
	}

	private boolean containsOnlyLocalChanges(TreePath path) {
		IResourceDiffTree tree = getDiffTree(path);
		ResourceTraversal[] traversals = getTraversals(path.getLastSegment());
		return !tree.hasMatchingDiffs(traversals, getNonLocalChangesFilter());
	}

	private ResourceTraversal[] getTraversals(Object element) {
		if (element instanceof ChangeSet) {
			ChangeSet set = (ChangeSet) element;
			return new ResourceTraversal[] { new ResourceTraversal(set.getResources(), IResource.DEPTH_ZERO, IResource.NONE) };
		}
		if (element instanceof IProject) {
			IProject project = (IProject) element;
			return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { project }, IResource.DEPTH_INFINITE, IResource.NONE) };
		}
		if (element instanceof IFile) {
			IFile file = (IFile) element;
			return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { file }, IResource.DEPTH_ZERO, IResource.NONE) };
		}
		if (element instanceof IFolder) {
			IFolder folder = (IFolder) element;
			if (getLayout().equals(IPreferenceIds.COMPRESSED_LAYOUT)) {
				return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { folder }, IResource.DEPTH_ONE, IResource.NONE) };
			} else if (getLayout().equals(IPreferenceIds.TREE_LAYOUT)) {
				return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { folder }, IResource.DEPTH_INFINITE, IResource.NONE) };
			} else if (getLayout().equals(IPreferenceIds.FLAT_LAYOUT)) {
				return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { folder }, IResource.DEPTH_ZERO, IResource.NONE) };
			}
		}
		return new ResourceTraversal[0];
	}
	
	private FastDiffFilter getNonLocalChangesFilter() {
		return new FastDiffFilter() {
			public boolean select(IDiff diff) {
				if (diff instanceof IThreeWayDiff && isVisible(diff)) {
					IThreeWayDiff twd = (IThreeWayDiff) diff;
					if (twd.getDirection() == IThreeWayDiff.OUTGOING
							|| twd.getDirection() == IThreeWayDiff.CONFLICTING) {
						return false;
					}
				}
				return true;
			}
		};
	}

	/* package */boolean isVisible(IDiff diff) {
		return ((SynchronizePageConfiguration)getSynchronizePageConfiguration()).isVisible(diff);
	}

	protected ResourceModelTraversalCalculator getTraversalCalculator() {
		return ResourceModelTraversalCalculator.getTraversalCalculator(getSynchronizePageConfiguration());
	}

	private ChangeSetContentProvider getContentProvider() {
		INavigatorContentExtension extension = getExtension();
		if (extension != null) {
			ITreeContentProvider provider = extension.getContentProvider();
			if (provider instanceof ChangeSetContentProvider) {
				return (ChangeSetContentProvider) provider;
			}
		}
		return null;
	}

	private INavigatorContentExtension getExtension() {
		INavigatorContentService service = getActionSite().getContentService();
		Set set = service.findContentExtensionsByTriggerPoint(getModelProvider());
		for (Iterator iter = set.iterator(); iter.hasNext();) {
			INavigatorContentExtension extension = (INavigatorContentExtension) iter.next();
			return extension;
		}
		return null;
	}

	private Object getModelProvider() {
		return ChangeSetModelProvider.getProvider();
	}

	private String getLayout() {
		return TeamUIPlugin.getPlugin().getPreferenceStore().getString(IPreferenceIds.SYNCVIEW_DEFAULT_LAYOUT);
	}

	public void setContext(ActionContext context) {
		super.setContext(context);
		if (context != null) {
			if (editChangeSet != null)
		        editChangeSet.selectionChanged((IStructuredSelection)getContext().getSelection());
			if (removeChangeSet != null)
	            removeChangeSet.selectionChanged((IStructuredSelection)getContext().getSelection());
			if (makeDefault != null)
		        makeDefault.selectionChanged((IStructuredSelection)getContext().getSelection());
		}
	}

	protected boolean isContentProviderEnabled() {
		ChangeSetContentProvider provider = getContentProvider();
		if (provider != null) {
			return provider.isEnabled();
		}
		return false;
	}

	/* package */ISynchronizePageConfiguration internalGetSynchronizePageConfiguration() {
		return getSynchronizePageConfiguration();
	}
}
