/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ui.synchronize.actions;

import java.lang.reflect.InvocationTargetException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Control;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.synchronize.FastSyncInfoFilter;
import org.eclipse.team.core.synchronize.FastSyncInfoFilter.SyncInfoDirectionFilter;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.internal.core.subscribers.ActiveChangeSet;
import org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager;
import org.eclipse.team.internal.core.subscribers.ChangeSet;
import org.eclipse.team.internal.ui.TeamUIMessages;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.team.internal.ui.synchronize.ChangeSetCapability;
import org.eclipse.team.internal.ui.synchronize.ChangeSetModelProvider;
import org.eclipse.team.internal.ui.synchronize.ChangeSetModelSorter;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.eclipse.team.ui.synchronize.SubscriberParticipant;
import org.eclipse.team.ui.synchronize.SynchronizeModelAction;
import org.eclipse.team.ui.synchronize.SynchronizeModelOperation;
import org.eclipse.team.ui.synchronize.SynchronizePageActionGroup;
import org.eclipse.ui.actions.BaseSelectionListenerAction;

/**
 * This action group contributes actions that support the management
 * of Change sets to a synchronize page.
 *
 * @since 3.1
 */
public class ChangeSetActionGroup extends SynchronizePageActionGroup {

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

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

	public static final FastSyncInfoFilter OUTGOING_RESOURCE_FILTER = new SyncInfoDirectionFilter(
			new int[] { SyncInfo.OUTGOING, SyncInfo.CONFLICTING });

	private class CreateChangeSetAction extends SynchronizeModelAction {

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

		@Override
		protected boolean needsToSaveDirtyEditors() {
			return false;
		}

		@Override
		protected FastSyncInfoFilter getSyncInfoFilter() {
			return OUTGOING_RESOURCE_FILTER;
		}

		@Override
		protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) {
			return new SynchronizeModelOperation(configuration, elements) {
				@Override
				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
					syncExec(() -> {
						ActiveChangeSet set = createChangeSet(getDiffs(getSyncInfoSet().getResources()));
						if (set != null) {
							getActiveChangeSetManager().add(set);
						}
					});
				}
			};
		}
	}

	private abstract class ChangeSetAction extends BaseSelectionListenerAction {

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

		@Override
		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 IAdaptable) {
					Object adapter = ((IAdaptable)first).getAdapter(ChangeSet.class);
					if (adapter instanceof ActiveChangeSet) {
						return (ActiveChangeSet)adapter;
					}
				}
			}
			return null;
		}
	}

	private class EditChangeSetAction extends ChangeSetAction {

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

		@Override
		public void run() {
			ActiveChangeSet set = getSelectedSet();
			if (set == null) return;
			editChangeSet(set);
		}
	}

	private class RemoveChangeSetAction extends ChangeSetAction {

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

		@Override
		public void run() {
			ActiveChangeSet set = getSelectedSet();
			if (set == null) return;
			if (MessageDialog.openConfirm(getConfiguration().getSite().getShell(), TeamUIMessages.ChangeSetActionGroup_0, NLS.bind(TeamUIMessages.ChangeSetActionGroup_1, new String[] { LegacyActionTools.escapeMnemonics(set.getTitle()) }))) { //
				getActiveChangeSetManager().remove(set);
			}
		}
	}

	private class MakeDefaultChangeSetAction extends ChangeSetAction {

		public MakeDefaultChangeSetAction(
				ISynchronizePageConfiguration configuration) {
			super(TeamUIMessages.ChangeLogModelProvider_9, configuration);
		}

		@Override
		protected boolean updateSelection(IStructuredSelection selection) {
			if (getSelectedSet() != null) {
				setText(TeamUIMessages.ChangeLogModelProvider_9);
				setChecked(getSelectedSet().equals(
						getActiveChangeSetManager().getDefaultSet()));
			} else {
				setText(TeamUIMessages.ChangeLogModelProvider_10);
				setChecked(false);
			}
			return true;
		}

		@Override
		public void run() {
			getActiveChangeSetManager().makeDefault(
					isChecked() ? getSelectedSet() : null);
			if (getSelectedSet() == null) {
				setChecked(false); // keep unchecked
			}
		}

	}

	private class AddToChangeSetAction extends SynchronizeModelAction {

		private final ActiveChangeSet set;

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

		@Override
		protected FastSyncInfoFilter getSyncInfoFilter() {
			return OUTGOING_RESOURCE_FILTER;
		}

		@Override
		protected boolean needsToSaveDirtyEditors() {
			return false;
		}

		@Override
		protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) {
			return new SynchronizeModelOperation(configuration, elements) {
				@Override
				public void run(IProgressMonitor monitor)
						throws InvocationTargetException, InterruptedException {
					IResource[] resources = getSyncInfoSet().getResources();
					if (set != null) {
						IDiff[] diffArray = getDiffs(resources);
						set.add(diffArray);
					} else {
						ChangeSet[] sets = getActiveChangeSetManager().getSets();
						for (int i = 0; i < sets.length; i++) {
							ActiveChangeSet activeSet = (ActiveChangeSet)sets[i];
							activeSet.remove(resources);
						}
					}
				}
			};
		}
	}

	/* *****************************************************************************
	 * 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();
		}

		@Override
		public void run() {
			if (isChecked() && sortCriteria != criteria) {
				sortCriteria = criteria;
				String key = getSettingsKey();
				IDialogSettings pageSettings = getConfiguration().getSite().getPageSettings();
				if(pageSettings != null) {
					pageSettings.put(key, criteria);
				}
				update();
				provider.setViewerSorter(getViewerSorter());
			}
		}

		public void update() {
			setChecked(criteria == sortCriteria);
		}

		protected String getSettingsKey() {
			return P_LAST_COMMENTSORT;
		}
	}

	/*
	 * The model provider for this action group
	 */
	private ChangeSetModelProvider provider;

	/*
	 * The actions created by this group
	 */
	private MenuManager sortByComment;
	private CreateChangeSetAction createChangeSet;
	private MenuManager addToChangeSet;
	private EditChangeSetAction editChangeSet;
	private RemoveChangeSetAction removeChangeSet;
	private MakeDefaultChangeSetAction makeDefault;

	private SynchronizePageActionGroup subActions;

	/*
	 * The currently chosen sort criteria
	 */
	private int sortCriteria = ChangeSetModelSorter.DATE;

	public static int getSortCriteria(ISynchronizePageConfiguration configuration) {
		int sortCriteria = ChangeSetModelSorter.DATE;
		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 ChangeSetModelSorter.COMMENT:
		case ChangeSetModelSorter.DATE:
		case ChangeSetModelSorter.USER:
			break;
		default:
			sortCriteria = ChangeSetModelSorter.DATE;
			break;
		}
		return sortCriteria;
	}

	public ChangeSetActionGroup(ChangeSetModelProvider provider) {
		this.provider = provider;
	}

	@Override
	public void initialize(ISynchronizePageConfiguration configuration) {
		super.initialize(configuration);

		if (getChangeSetCapability().supportsCheckedInChangeSets()) {
			sortCriteria = getSortCriteria(configuration);
			sortByComment = new MenuManager(TeamUIMessages.ChangeLogModelProvider_0a);
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_1a, ChangeSetModelSorter.COMMENT));
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_2a, ChangeSetModelSorter.DATE));
			sortByComment.add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_3a, ChangeSetModelSorter.USER));
		}

		if (getChangeSetCapability().supportsActiveChangeSets()) {
			addToChangeSet = new MenuManager(TeamUIMessages.ChangeLogModelProvider_12);
			addToChangeSet.setRemoveAllWhenShown(true);
			addToChangeSet.addMenuListener(manager -> addChangeSets(manager));
			createChangeSet = new CreateChangeSetAction(configuration);
			addToChangeSet.add(createChangeSet);
			addToChangeSet.add(new Separator());
			editChangeSet = new EditChangeSetAction(configuration);
			makeDefault = new MakeDefaultChangeSetAction(configuration);
			removeChangeSet = new RemoveChangeSetAction(configuration);
		}

		subActions = getChangeSetCapability().getActionGroup();
		if (subActions != null) {
			subActions.initialize(configuration);
		}
	}

	@Override
	public void fillContextMenu(IMenuManager menu) {
		if (getChangeSetCapability().enableCheckedInChangeSetsFor(getConfiguration())) {
			appendToGroup(menu, ISynchronizePageConfiguration.SORT_GROUP, sortByComment);
		}
		if (getChangeSetCapability().enableActiveChangeSetsFor(getConfiguration())) {
			appendToGroup(
					menu,
					CHANGE_SET_GROUP,
					addToChangeSet);
			appendToGroup(
					menu,
					CHANGE_SET_GROUP,
					editChangeSet);
			appendToGroup(
					menu,
					CHANGE_SET_GROUP,
					removeChangeSet);
			appendToGroup(
					menu,
					CHANGE_SET_GROUP,
					makeDefault);
		}
		if (subActions != null) {
			subActions.fillContextMenu(menu);
		}
	}

	protected void addChangeSets(IMenuManager manager) {
		ChangeSet[] sets = getActiveChangeSetManager().getSets();
		Arrays.sort(sets, new Comparator<ChangeSet>() {
			private Collator collator = Collator.getInstance();
			@Override
			public int compare(ChangeSet o1, ChangeSet o2) {
				return collator.compare(o1.getName(), o2.getName());
			}
		});
		ISelection selection = getContext().getSelection();
		createChangeSet.selectionChanged(selection);
		addToChangeSet.add(createChangeSet);
		addToChangeSet.add(new Separator());
		for (int i = 0; i < sets.length; i++) {
			ActiveChangeSet set = (ActiveChangeSet)sets[i];
			AddToChangeSetAction action = new AddToChangeSetAction(getConfiguration(), set, selection);
			manager.add(action);
		}
		addToChangeSet.add(new Separator());
		// Action that removes change set resources
		addToChangeSet.add(new AddToChangeSetAction(getConfiguration(), null, selection));
	}

	/**
	 * Return the change set manager for the current page.
	 * @return the change set manager for the current page
	 */
	protected ActiveChangeSetManager getActiveChangeSetManager() {
		return getChangeSetCapability().getActiveChangeSetManager();
	}

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


	@Override
	public void updateActionBars() {
		if (editChangeSet != null)
			editChangeSet.selectionChanged((IStructuredSelection)getContext().getSelection());
		if (removeChangeSet != null)
			removeChangeSet.selectionChanged((IStructuredSelection)getContext().getSelection());
		if (makeDefault != null)
			makeDefault.selectionChanged((IStructuredSelection)getContext().getSelection());
		super.updateActionBars();
	}

	private void syncExec(final Runnable runnable) {
		final Control ctrl = getConfiguration().getPage().getViewer().getControl();
		if (ctrl != null && !ctrl.isDisposed()) {
			ctrl.getDisplay().syncExec(() -> {
				if (!ctrl.isDisposed()) {
					runnable.run();
				}
			});
		}
	}

	/**
	 * Return a viewer sorter that utilizes the sort criteria
	 * selected by the user.
	 * @return a sorter
	 */
	public ViewerSorter getViewerSorter() {
		return new ChangeSetModelSorter(provider, sortCriteria);
	}

	private ActiveChangeSet createChangeSet(IDiff[] diffs) {
		return getChangeSetCapability().createChangeSet(getConfiguration(), diffs);
	}

	private void editChangeSet(ActiveChangeSet set) {
		getChangeSetCapability().editChangeSet(getConfiguration(), set);
	}

	private ChangeSetCapability getChangeSetCapability() {
		return provider.getChangeSetCapability();
	}

	private IDiff[] getDiffs(IResource[] resources) {
		List<IDiff> diffs = new ArrayList<>();
		Subscriber s = ((SubscriberParticipant)getConfiguration().getParticipant()).getSubscriber();
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			try {
				IDiff diff = s.getDiff(resource);
				if (diff != null)
					diffs.add(diff);
			} catch (CoreException e) {
				TeamUIPlugin.log(e);
			}
		}
		IDiff[] diffArray = diffs.toArray(new IDiff[diffs.size()]);
		return diffArray;
	}
}
