/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *     Benjamin Muskalla (b.muskalla@gmx.net) - Bug 149672 [Patch] Create Patch wizard should remember previous settings
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.wizards;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.core.Team;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IDiffVisitor;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.core.synchronize.SyncInfoSet;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.ICVSFile;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.client.Diff;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.IHelpContextIds;
import org.eclipse.team.internal.ccvs.ui.operations.*;
import org.eclipse.team.internal.ccvs.ui.subscriber.CreatePatchWizardParticipant;
import org.eclipse.team.internal.ccvs.ui.subscriber.WorkspaceSynchronizeParticipant;
import org.eclipse.team.internal.core.subscribers.SubscriberSyncInfoCollector;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.navigator.ResourceComparator;

/**
 * A wizard for creating a patch file by running the CVS diff command.
 */
public class GenerateDiffFileWizard extends Wizard {

	//The initial size of this wizard.
	private final static int INITIAL_WIDTH = 300;
	private final static int INITIAL_HEIGHT = 350;

	public static void run(IWorkbenchPart part, final IResource[] resources, boolean unifiedSelectionEnabled) {
		final String title = CVSUIMessages.GenerateCVSDiff_title;
		final GenerateDiffFileWizard wizard = new GenerateDiffFileWizard(part,resources, unifiedSelectionEnabled);
		wizard.setWindowTitle(title);
		WizardDialog dialog = new WizardDialog(part.getSite().getShell(), wizard);
		dialog.setMinimumPageSize(INITIAL_WIDTH, INITIAL_HEIGHT);
		dialog.open();
	}

	public static void run(IWorkbenchPart part, final IResource[] resources) {
		GenerateDiffFileWizard.run(part,resources,true);
	}

	/**
	 * Page to select a patch file. Overriding validatePage was necessary to allow
	 * entering a file name that already exists.
	 */
	public class LocationPage extends WizardPage {

		/**
		 * The possible locations to save a patch.
		 */
		public final static int CLIPBOARD = 1;
		public final static int FILESYSTEM = 2;
		public final static int WORKSPACE = 3;

		/**
		 * GUI controls for clipboard (cp), filesystem (fs) and workspace (ws).
		 */
		private Button cpRadio;

		private Button fsRadio;
		protected Text fsPathText;
		private Button fsBrowseButton;
		private boolean fsBrowsed = false;

		private Button wsRadio;
		protected Text wsPathText;
		private Button wsBrowseButton;
		private boolean wsBrowsed = false;

		protected CreatePatchWizardParticipant fParticipant;
		private Button chgSelectAll;
		private Button chgDeselectAll;

		/**
		 * State information of this page, updated by the listeners.
		 */
		protected boolean canValidate;
		protected boolean pageValid;
		protected IContainer wsSelectedContainer;
		protected IPath[] foldersToCreate;
		protected int selectedLocation;

		/**
		 * The default values store used to initialize the selections.
		 */
		private final DefaultValuesStore store;


		class LocationPageContentProvider extends BaseWorkbenchContentProvider {
			//Never show closed projects
			boolean showClosedProjects=false;

			@Override
			public Object[] getChildren(Object element) {
				if (element instanceof IWorkspace) {
					// check if closed projects should be shown
					IProject[] allProjects = ((IWorkspace) element).getRoot().getProjects();
					if (showClosedProjects)
						return allProjects;

					ArrayList<IProject> accessibleProjects = new ArrayList<>();
					for (int i = 0; i < allProjects.length; i++) {
						if (allProjects[i].isOpen()) {
							accessibleProjects.add(allProjects[i]);
						}
					}
					return accessibleProjects.toArray();
				}

				return super.getChildren(element);
			}
		}

		class WorkspaceDialog extends TitleAreaDialog {

			protected TreeViewer wsTreeViewer;
			protected Text wsFilenameText;
			protected Image dlgTitleImage;

			private boolean modified = false;

			public WorkspaceDialog(Shell shell) {
				super(shell);
			}

			@Override
			protected Control createContents(Composite parent) {
				Control control = super.createContents(parent);
				setTitle(CVSUIMessages.WorkspacePatchDialogTitle);
				setMessage(CVSUIMessages.WorkspacePatchDialogDescription);
				//create title image
				dlgTitleImage = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_WIZBAN_DIFF).createImage();
				setTitleImage(dlgTitleImage);

				return control;
			}

			@Override
			protected Control createDialogArea(Composite parent){
				Composite parentComposite = (Composite) super.createDialogArea(parent);

				// create a composite with standard margins and spacing
				Composite composite = new Composite(parentComposite, SWT.NONE);
				GridLayout layout = new GridLayout();
				layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
				layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
				layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
				layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
				composite.setLayout(layout);
				composite.setLayoutData(new GridData(GridData.FILL_BOTH));
				composite.setFont(parentComposite.getFont());

				getShell().setText(CVSUIMessages.GenerateDiffFileWizard_9);

				wsTreeViewer = new TreeViewer(composite, SWT.BORDER);
				final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
				gd.widthHint= 550;
				gd.heightHint= 250;
				wsTreeViewer.getTree().setLayoutData(gd);

				wsTreeViewer.setContentProvider(new LocationPageContentProvider());
				wsTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
				wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
				wsTreeViewer.setInput(ResourcesPlugin.getWorkspace());

				//Open to whatever is selected in the workspace field
				IPath existingWorkspacePath = new Path(wsPathText.getText());
				//Ensure that this workspace path is valid
				IResource selectedResource = ResourcesPlugin.getWorkspace().getRoot().findMember(existingWorkspacePath);
				if (selectedResource != null) {
					wsTreeViewer.expandToLevel(selectedResource, 0);
					wsTreeViewer.setSelection(new StructuredSelection(selectedResource));
				}

				final Composite group = new Composite(composite, SWT.NONE);
				layout = new GridLayout(2, false);
				layout.marginWidth = 0;
				group.setLayout(layout);
				group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

				final Label label = new Label(group, SWT.NONE);
				label.setLayoutData(new GridData());
				label.setText(CVSUIMessages.Fi_le_name__9);

				wsFilenameText = new Text(group,SWT.BORDER);
				wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

				setupListeners();

				return parent;
			}

			@Override
			protected Button createButton(Composite parent, int id,
					String label, boolean defaultButton) {
				Button button = super.createButton(parent, id, label,
						defaultButton);
				if (id == IDialogConstants.OK_ID) {
					button.setEnabled(false);
				}
				return button;
			}

			private void validateDialog() {
				String fileName = wsFilenameText.getText();

				if (fileName.equals("")) { //$NON-NLS-1$
					if (modified) {
						setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_2);
						getButton(IDialogConstants.OK_ID).setEnabled(false);
						return;
					} else {
						setErrorMessage(null);
						getButton(IDialogConstants.OK_ID).setEnabled(false);
						return;
					}
				}

				// make sure that the filename is valid
				if (!(ResourcesPlugin.getWorkspace().validateName(fileName,
						IResource.FILE)).isOK() && modified) {
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_5);
					getButton(IDialogConstants.OK_ID).setEnabled(false);
					return;
				}

				// Make sure that a container has been selected
				if (getSelectedContainer() == null) {
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_0);
					getButton(IDialogConstants.OK_ID).setEnabled(false);
					return;
				} else {
					IWorkspace workspace = ResourcesPlugin.getWorkspace();
					IPath fullPath = wsSelectedContainer.getFullPath().append(
							fileName);
					if (workspace.getRoot().getFolder(fullPath).exists()) {
						setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_FolderExists);
						getButton(IDialogConstants.OK_ID).setEnabled(false);
						return;
					}
				}

				setErrorMessage(null);
				getButton(IDialogConstants.OK_ID).setEnabled(true);
			}

			@Override
			protected void okPressed() {
				IFile file = wsSelectedContainer.getFile(new Path(
						wsFilenameText.getText()));
				if (file != null)
					wsPathText.setText(file.getFullPath().toString());

				validatePage();
				super.okPressed();
			}

			private IContainer getSelectedContainer() {
				Object obj = wsTreeViewer.getStructuredSelection().getFirstElement();
				if (obj instanceof IContainer) {
					wsSelectedContainer = (IContainer) obj;
				} else if (obj instanceof IFile) {
					wsSelectedContainer = ((IFile) obj).getParent();
				}
				return wsSelectedContainer;
			}

			@Override
			protected void cancelPressed() {
				validatePage();
				super.cancelPressed();
			}

			@Override
			public boolean close() {
				if (dlgTitleImage != null)
					dlgTitleImage.dispose();
				return super.close();
			}

			void setupListeners(){
				wsTreeViewer.addSelectionChangedListener(
						event -> {
							IStructuredSelection s = event.getStructuredSelection();
							Object obj=s.getFirstElement();
							if (obj instanceof IContainer)
								wsSelectedContainer = (IContainer) obj;
							else if (obj instanceof IFile){
								IFile tempFile = (IFile) obj;
								wsSelectedContainer = tempFile.getParent();
								wsFilenameText.setText(tempFile.getName());
							}
							validateDialog();
						});

				wsTreeViewer.addDoubleClickListener(
						event -> {
							ISelection s= event.getSelection();
							if (s instanceof IStructuredSelection) {
								Object item = ((IStructuredSelection)s).getFirstElement();
								if (wsTreeViewer.getExpandedState(item))
									wsTreeViewer.collapseToLevel(item, 1);
								else
									wsTreeViewer.expandToLevel(item, 1);
							}
							validateDialog();
						});

				wsFilenameText.addModifyListener(e -> {
					modified = true;
					validateDialog();
				});
			}
		}

		LocationPage(String pageName, String title, ImageDescriptor image, DefaultValuesStore store) {
			super(pageName, title, image);
			setPageComplete(false);
			this.store= store;
			this.canValidate=false;
		}

		/**
		 * Allow the user to finish if a valid file has been entered.
		 */
		protected boolean validatePage() {

			if (!canValidate)
				return false;

			switch (selectedLocation) {
			case WORKSPACE:
				pageValid= validateWorkspaceLocation();
				break;
			case FILESYSTEM:
				pageValid= validateFilesystemLocation();
				break;
			case CLIPBOARD:
				pageValid= true;
				break;
			}

			if ((resources = getSelectedResources()).length == 0) {
				pageValid = false;
				setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_noChangesSelected);
			}

			/**
			 * Avoid draw flicker by clearing error message
			 * if all is valid.
			 */
			if (pageValid) {
				setMessage(null);
				setErrorMessage(null);
			}
			setPageComplete(pageValid);
			return pageValid;
		}

		/**
		 * The following conditions must hold for the file system location
		 * to be valid:
		 * - the path must be valid and non-empty
		 * - the path must be absolute
		 * - the specified file must be of type file
		 * - the parent must exist (new folders can be created via the browse button)
		 */
		private boolean validateFilesystemLocation() {
			final String pathString= fsPathText.getText().trim();
			if (pathString.length() == 0 || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$
				if (fsBrowsed)
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_0);
				else
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_browseFilesystem);
				return false;
			}

			final File file= new File(pathString);
			if (!file.isAbsolute()) {
				setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_0);
				return false;
			}

			if (file.isDirectory()) {
				setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_2);
				return false;
			}

			if (pathString.endsWith("/") || pathString.endsWith("\\")) {  //$NON-NLS-1$//$NON-NLS-2$
				setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_3);
				return false;
			}

			final File parent= file.getParentFile();
			if (!(parent.exists() && parent.isDirectory())) {
				setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_3);
				return false;
			}
			return true;
		}

		/**
		 * The following conditions must hold for the workspace location to be valid:
		 * - a parent must be selected in the workspace tree view
		 * - the resource name must be valid
		 */
		private boolean validateWorkspaceLocation() {
			//make sure that the field actually has a filename in it - making
			//sure that the user has had a chance to browse the workspace first
			if (wsPathText.getText().equals("")){ //$NON-NLS-1$
				if (selectedLocation ==WORKSPACE && wsBrowsed)
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_5);
				else
					setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_4);
				return false;
			}

			//Make sure that all the segments but the last one (i.e. project + all
			//folders) exist - file doesn't have to exist. It may have happened that
			//some folder refactoring has been done since this path was last saved.
			//
			// The path will always be in format project/{folders}*/file - this
			// is controlled by the workspace location dialog and by
			// validatePath method when path has been entered manually.


			IPath pathToWorkspaceFile = new Path(wsPathText.getText());
			IStatus status = ResourcesPlugin.getWorkspace().validatePath(wsPathText.getText(), IResource.FILE);
			if (status.isOK()) {
				//Trim file name from path
				IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
				IResource container =ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
				if (container == null) {
					if (selectedLocation == WORKSPACE)
						setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_4);
					return false;
				} else if (!container.isAccessible()) {
					if (selectedLocation == WORKSPACE)
						setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_ProjectClosed);
					return false;
				} else {
					if (ResourcesPlugin.getWorkspace().getRoot().getFolder(
							pathToWorkspaceFile).exists()) {
						setErrorMessage(CVSUIMessages.GenerateDiffFileWizard_FolderExists);
						return false;
					}
				}
			} else {
				setErrorMessage(status.getMessage());
				return false;
			}

			return true;
		}

		/**
		 * Answers a full path to a file system file or <code>null</code> if the user
		 * selected to save the patch in the clipboard.
		 */
		public File getFile() {
			if (pageValid && selectedLocation == FILESYSTEM) {
				return new File(fsPathText.getText().trim());
			}
			if (pageValid && selectedLocation == WORKSPACE) {
				final String filename= wsPathText.getText().trim();
				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
				final IFile file= root.getFile(new Path(filename));
				return file.getLocation().toFile();
			}
			return null;
		}

		/**
		 * Answers the workspace string entered in the dialog or <code>null</code> if the user
		 * selected to save the patch in the clipboard or file system.
		 */
		public String getWorkspaceLocation() {

			if (pageValid && selectedLocation == WORKSPACE) {
				final String filename= wsPathText.getText().trim();
				return filename;
			}
			return null;
		}

		/**
		 * Get the selected workspace resource if the patch is to be saved in the
		 * workspace, or null otherwise.
		 */
		public IResource getResource() {
			if (pageValid && selectedLocation == WORKSPACE) {
				IPath pathToWorkspaceFile = new Path(wsPathText.getText().trim());
				//Trim file name from path
				IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
				return ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
			}
			return null;
		}

		/**
		 * Allow the user to chose to save the patch to the workspace or outside
		 * of the workspace.
		 */
		@Override
		public void createControl(Composite parent) {

			final Composite composite= new Composite(parent, SWT.NULL);
			composite.setLayout(new GridLayout());
			setControl(composite);
			initializeDialogUnits(composite);

			// set F1 help
			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.PATCH_SELECTION_PAGE);

			//Create a location group
			setupLocationControls(composite);

			initializeDefaultValues();

			fParticipant = new CreatePatchWizardParticipant(new ResourceScope(((GenerateDiffFileWizard)this.getWizard()).resources), (GenerateDiffFileWizard) this.getWizard());
			try {
				getAllOutOfSync();
			} catch (CVSException e) {}

			final PixelConverter converter= new PixelConverter(parent);
			createChangesArea(composite, converter);

			createSelectionButtons(composite);

			Dialog.applyDialogFont(parent);

			/**
			 * Ensure the page is in a valid state.
			 */
			/*if (!validatePage()) {
				store.storeRadioSelection(CLIPBOARD);
				initializeDefaultValues();
				validatePage();
			}
			pageValid= true;*/
			validatePage();

			updateEnablements();
			setupListeners();
		}


		private void createSelectionButtons(Composite composite) {
			final Composite buttonGroup = new Composite(composite,SWT.NONE);
			GridLayout layout = new GridLayout();
			layout.numColumns = 2;
			layout.marginWidth = 0;
			layout.marginHeight = 0;
			layout.horizontalSpacing = 0;
			layout.verticalSpacing = 0;
			buttonGroup.setLayout(layout);
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
					| GridData.VERTICAL_ALIGN_CENTER);
			buttonGroup.setLayoutData(data);

			chgSelectAll = createSelectionButton(CVSUIMessages.GenerateDiffFileWizard_SelectAll, buttonGroup);
			chgDeselectAll = createSelectionButton(CVSUIMessages.GenerateDiffFileWizard_DeselectAll, buttonGroup);
		}

		private Button createSelectionButton(String buttonName, Composite buttonGroup) {
			Button button = new Button(buttonGroup,SWT.PUSH);
			button.setText(buttonName);
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
			int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
			data.widthHint = Math.max(widthHint, minSize.x);
			button.setLayoutData(data);
			return button;
		}


		/**
		 * Setup the controls for the location.
		 */
		private void setupLocationControls(final Composite parent) {
			final Composite composite = new Composite(parent, SWT.NULL);
			GridLayout gridLayout = new GridLayout();
			gridLayout.numColumns = 3;
			composite.setLayout(gridLayout);
			composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

			// clipboard
			GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
			gd.horizontalSpan = 3;
			cpRadio = new Button(composite, SWT.RADIO);
			cpRadio.setText(CVSUIMessages.Save_To_Clipboard_2);
			cpRadio.setLayoutData(gd);

			// filesystem
			fsRadio = new Button(composite, SWT.RADIO);
			fsRadio.setText(CVSUIMessages.Save_In_File_System_3);

			fsPathText = new Text(composite, SWT.BORDER);
			gd = new GridData(GridData.FILL_HORIZONTAL);
			fsPathText.setLayoutData(gd);

			fsBrowseButton = new Button(composite, SWT.PUSH);
			fsBrowseButton.setText(CVSUIMessages.Browse____4);
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
			int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT,
					SWT.DEFAULT, true);
			data.widthHint = Math.max(widthHint, minSize.x);
			fsBrowseButton.setLayoutData(data);

			// workspace
			wsRadio = new Button(composite, SWT.RADIO);
			wsRadio.setText(CVSUIMessages.Save_In_Workspace_7);

			wsPathText = new Text(composite, SWT.BORDER);
			gd = new GridData(GridData.FILL_HORIZONTAL);
			wsPathText.setLayoutData(gd);

			wsBrowseButton = new Button(composite, SWT.PUSH);
			wsBrowseButton.setText(CVSUIMessages.Browse____4);
			data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
			widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			minSize = fsBrowseButton
			.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
			data.widthHint = Math.max(widthHint, minSize.x);
			wsBrowseButton.setLayoutData(data);

			// change the cpRadio layout to be of the same height as other rows' layout
			((GridData)cpRadio.getLayoutData()).heightHint = minSize.y;
		}

		private ParticipantPagePane fPagePane;
		private PageBook bottomChild;
		private ISynchronizePageConfiguration fConfiguration;

		private void createChangesArea(Composite parent, PixelConverter converter) {

			int size = fParticipant.getSyncInfoSet().size();
			if (size > getFileDisplayThreshold()) {
				// Create a page book to allow eventual inclusion of changes
				bottomChild = new PageBook(parent, SWT.NONE);
				bottomChild.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT, SWT.DEFAULT, SWT.FILL, SWT.FILL, true, false));
				// Create composite for showing the reason for not showing the changes and a button to show them
				Composite changeDesc = new Composite(bottomChild, SWT.NONE);
				changeDesc.setLayout(SWTUtils.createGridLayout(1, converter, SWTUtils.MARGINS_NONE));
				SWTUtils.createLabel(changeDesc, NLS.bind(CVSUIMessages.CommitWizardCommitPage_1, new String[] { Integer.toString(size), Integer.toString(getFileDisplayThreshold()) }));
				Button showChanges = new Button(changeDesc, SWT.PUSH);
				showChanges.setText(CVSUIMessages.CommitWizardCommitPage_5);
				showChanges.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						showChangesPane();
					}
				});
				showChanges.setLayoutData(new GridData());
				bottomChild.showPage(changeDesc);
			} else {
				final Composite composite= new Composite(parent, SWT.NONE);
				composite.setLayout(SWTUtils.createGridLayout(1, converter, SWTUtils.MARGINS_NONE));
				composite.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT, SWT.DEFAULT, SWT.FILL, SWT.FILL, true, true));

				createPlaceholder(composite);

				Control c = createChangesPage(composite, fParticipant);
				c.setLayoutData(SWTUtils.createHVFillGridData());
			}
		}

		protected void showChangesPane() {
			Control c = createChangesPage(bottomChild, fParticipant);
			bottomChild.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT, SWT.DEFAULT, SWT.FILL, SWT.FILL, true, true));
			bottomChild.showPage(c);
			Dialog.applyDialogFont(getControl());
			((Composite)getControl()).layout();
		}

		private Control createChangesPage(final Composite composite, WorkspaceSynchronizeParticipant participant) {
			fConfiguration= participant.createPageConfiguration();
			fPagePane= new ParticipantPagePane(getShell(), true /* modal */, fConfiguration, participant);
			Control control = fPagePane.createPartControl(composite);
			return control;
		}

		@Override
		public void dispose() {
			if (fPagePane != null)
				fPagePane.dispose();
			if (fParticipant != null)
				fParticipant.dispose();
			super.dispose();
		}

		private int getFileDisplayThreshold() {
			return CVSUIPlugin.getPlugin().getPreferenceStore().getInt(ICVSUIConstants.PREF_COMMIT_FILES_DISPLAY_THRESHOLD);
		}

		private void createPlaceholder(final Composite composite) {
			final Composite placeholder= new Composite(composite, SWT.NONE);
			placeholder.setLayoutData(new GridData(SWT.DEFAULT, convertHorizontalDLUsToPixels(IDialogConstants.VERTICAL_SPACING) /3));
		}
		/**
		 * Initialize the controls with the saved default values which are
		 * obtained from the DefaultValuesStore.
		 */
		private void initializeDefaultValues() {

			selectedLocation= store.getLocationSelection();

			updateRadioButtons();

			/**
			 * Text fields.
			 */
			// We need to ensure that we have a valid workspace path - user
			//could have altered workspace since last time this was saved
			wsPathText.setText(store.getWorkspacePath());
			if(!validateWorkspaceLocation()) {
				wsPathText.setText(""); //$NON-NLS-1$

				//Don't open wizard with an error - instead change selection
				//to clipboard
				if (selectedLocation == WORKSPACE){
					//clear the error message caused by the workspace not having
					//any workspace path entered
					setErrorMessage(null);
					selectedLocation=CLIPBOARD;
					updateRadioButtons();
				}
			}
			// Do the same thing for the filesystem field
			fsPathText.setText(store.getFilesystemPath());
			if (!validateFilesystemLocation()) {
				fsPathText.setText(""); //$NON-NLS-1$
				if (selectedLocation == FILESYSTEM) {
					setErrorMessage(null);
					selectedLocation = CLIPBOARD;
					updateRadioButtons();
				}
			}

		}

		private void updateRadioButtons() {
			/**
			 * Radio buttons
			 */
			cpRadio.setSelection(selectedLocation == CLIPBOARD);
			fsRadio.setSelection(selectedLocation == FILESYSTEM);
			wsRadio.setSelection(selectedLocation == WORKSPACE);
		}

		/**
		 * Setup all the listeners for the controls.
		 */
		private void setupListeners() {

			cpRadio.addListener(SWT.Selection, event -> {
				selectedLocation= CLIPBOARD;
				validatePage();
				updateEnablements();
			});
			fsRadio.addListener(SWT.Selection, event -> {
				selectedLocation= FILESYSTEM;
				validatePage();
				updateEnablements();
			});

			wsRadio.addListener(SWT.Selection, event -> {
				selectedLocation= WORKSPACE;
				validatePage();
				updateEnablements();
			});

			ModifyListener pathTextModifyListener = e -> validatePage();
			fsPathText.addModifyListener(pathTextModifyListener);
			wsPathText.addModifyListener(pathTextModifyListener);

			fsBrowseButton.addListener(SWT.Selection, event -> {
				final FileDialog dialog = new FileDialog(getShell(), SWT.PRIMARY_MODAL | SWT.SAVE);
				if (pageValid) {
					final File file= new File(fsPathText.getText());
					dialog.setFilterPath(file.getParent());
				}
				dialog.setText(CVSUIMessages.Save_Patch_As_5);
				dialog.setFileName(CVSUIMessages.patch_txt_6);
				final String path = dialog.open();
				fsBrowsed = true;
				if (path != null) {
					fsPathText.setText(new Path(path).toOSString());
				}
				validatePage();
			});



			wsBrowseButton.addListener(SWT.Selection, event -> {
				final WorkspaceDialog dialog = new WorkspaceDialog(getShell());
				wsBrowsed = true;
				dialog.open();
				validatePage();
			});


			chgSelectAll.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					initCheckedItems();
					//Only bother changing isPageComplete state if the current state
					//is not enabled
					if (!isPageComplete())
						setPageComplete(validatePage());
				}
			});

			chgDeselectAll.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					ISynchronizePage page = fConfiguration.getPage();
					if (page != null){
						Viewer viewer = page.getViewer();
						if (viewer instanceof CheckboxTreeViewer) {
							CheckboxTreeViewer treeViewer =(CheckboxTreeViewer)viewer;
							treeViewer.setCheckedElements(new Object[0]);
						}
					}
					//Only bother changing isPageComplete state if the current state
					//is enabled
					if (isPageComplete())
						setPageComplete(validatePage());
				}
			});

			ISynchronizePage page = fConfiguration.getPage();
			if (page != null) {
				Viewer viewer = page.getViewer();
				if (viewer instanceof CheckboxTreeViewer) {
					((CheckboxTreeViewer)viewer).addCheckStateListener(event -> setPageComplete(validatePage()));
				}
			}
		}

		protected void initCheckedItems() {
			ISynchronizePage page = fConfiguration.getPage();
			if (page != null) {
				Viewer viewer = page.getViewer();
				if (viewer instanceof CheckboxTreeViewer) {
					TreeItem[] items=((CheckboxTreeViewer)viewer).getTree().getItems();
					for (int i = 0; i < items.length; i++) {
						((CheckboxTreeViewer)viewer).setChecked(items[i].getData(), true);
					}
				}
			}
		}

		protected IResource[] getSelectedResources() {
			ISynchronizePage page = fConfiguration.getPage();
			if (page != null) {
				Viewer viewer = page.getViewer();
				if (viewer instanceof CheckboxTreeViewer) {
					Object[] elements = ((CheckboxTreeViewer)viewer).getCheckedElements();
					IResource[]selectedResources = Utils.getResources(elements);
					ArrayList<IResource> result = new ArrayList<>();
					for (int i = 0; i < selectedResources.length; i++) {
						IResource resource = selectedResources[i];
						if (fConfiguration.getSyncInfoSet().getSyncInfo(resource) != null) {
							result.add(resource);
						}
					}
					return result.toArray(new IResource[result.size()]);
				}
			}
			return new IResource[0];
		}

		/**
		 * Enable and disable controls based on the selected radio button.
		 */
		public void updateEnablements() {
			fsBrowseButton.setEnabled(selectedLocation == FILESYSTEM);
			fsPathText.setEnabled(selectedLocation == FILESYSTEM);
			if (selectedLocation == FILESYSTEM)
				fsBrowsed=false;
			wsPathText.setEnabled(selectedLocation == WORKSPACE);
			wsBrowseButton.setEnabled(selectedLocation == WORKSPACE);
			if (selectedLocation == WORKSPACE)
				wsBrowsed=false;
		}

		public int getSelectedLocation() {
			return selectedLocation;
		}

		private SyncInfoSet getAllOutOfSync() throws CVSException {
			final SubscriberSyncInfoCollector syncInfoCollector = fParticipant.getSubscriberSyncInfoCollector();
			//WaitForChangesJob waits for the syncInfoCollector to get all the changes
			//before checking off the tree items and validating the page
			class WaitForChangesJob extends Job{
				LocationPage fLocationPage;

				public WaitForChangesJob(LocationPage page) {
					super(""); //$NON-NLS-1$
					fLocationPage=page;
				}
				@Override
				public IStatus run(IProgressMonitor monitor) {
					monitor.beginTask(CVSUIMessages.CommitWizard_4, IProgressMonitor.UNKNOWN);
					syncInfoCollector.waitForCollector(monitor);
					Utils.syncExec((Runnable) () -> {
						fLocationPage.initCheckedItems();
						fLocationPage.canValidate=true;
						fLocationPage.validatePage();
					}, getControl());
					monitor.done();
					return Status.OK_STATUS;
				}
			}
			WaitForChangesJob job =new WaitForChangesJob(this);
			//Don't need the job in the UI, make it a system job
			job.setSystem(true);
			job.schedule();
			return fParticipant.getSyncInfoSet();
		}

		public IFile findBinaryFile() {
			try {
				final IFile[] found = new IFile[1];
				fParticipant.getSubscriber().accept(resources, IResource.DEPTH_INFINITE, (IDiffVisitor) diff -> {
					if (isBinaryFile(diff))
						found[0] = getFile(diff);
					return true;
				});
				return found[0];
			} catch (CoreException e) {
				CVSUIPlugin.log(e);
			}
			return null;
		}

		protected boolean isBinaryFile(IDiff diff) {
			IFile file = getFile(diff);
			if (file != null) {
				ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file);
				try {
					byte[] bytes = cvsFile.getSyncBytes();
					if (bytes != null) {
						return ResourceSyncInfo.getKeywordMode(bytes).toMode().equals(
								Command.KSUBST_BINARY.toMode());
					}
				} catch (CVSException e) {
					CVSUIPlugin.log(e);
				}
				return (Team.getFileContentManager().getType(file) == Team.BINARY);
			}
			return false;
		}

		protected IFile getFile(IDiff diff) {
			IResource resource = ResourceDiffTree.getResourceFor(diff);
			if (resource instanceof IFile) {
				IFile file = (IFile) resource;
				return file;
			}
			return null;
		}

		public void removeBinaryFiles() {
			try {
				final List<IFile> nonBinaryFiles = new ArrayList<>();
				fParticipant.getSubscriber().accept(resources, IResource.DEPTH_INFINITE, (IDiffVisitor) diff -> {
					if (!isBinaryFile(diff)) {
						IFile file = getFile(diff);
						if (file != null)
							nonBinaryFiles.add(file);
					}
					return true;
				});
				resources = nonBinaryFiles
				.toArray(new IResource[nonBinaryFiles.size()]);
			} catch (CoreException e) {
				CVSUIPlugin.log(e);
			}
		}

	}

	/**
	 * Page to select the options for creating the patch.
	 */
	private class OptionsPage extends WizardPage {

		/**
		 * The possible file format to save a patch.
		 */
		public final static int FORMAT_UNIFIED = 1;
		public final static int FORMAT_CONTEXT = 2;
		public final static int FORMAT_STANDARD = 3;

		/**
		The possible root of the patch
		 */
		public final static int ROOT_WORKSPACE = 1;
		public final static int ROOT_PROJECT = 2;
		public final static int ROOT_SELECTION = 3;

		private Button unifiedDiffOption;
		private Button unified_workspaceRelativeOption; //multi-patch format
		private Button unified_projectRelativeOption; //full project path
		private Button unified_selectionRelativeOption; //use path of whatever is selected
		private Button contextDiffOption;
		private Button regularDiffOption;
		private final RadioButtonGroup diffTypeRadioGroup = new RadioButtonGroup();
		private final RadioButtonGroup unifiedRadioGroup = new RadioButtonGroup();

		private boolean patchHasCommonRoot=true;
		protected IPath patchRoot=ResourcesPlugin.getWorkspace().getRoot().getFullPath();

		private final DefaultValuesStore store;

		/**
		 * Constructor for PatchFileCreationOptionsPage.
		 * 
		 * @param pageName
		 *            the name of the page
		 * 
		 * @param title
		 *            the title for this wizard page, or <code>null</code> if
		 *            none
		 * @param titleImage
		 *            the image descriptor for the title of this wizard page, or
		 *            <code>null</code> if none
		 * @param store
		 *            the value store where the page stores it's data
		 */
		protected OptionsPage(String pageName, String title,
				ImageDescriptor titleImage, DefaultValuesStore store) {
			super(pageName, title, titleImage);
			this.store = store;
		}

		@Override
		public void createControl(Composite parent) {
			Composite composite= new Composite(parent, SWT.NULL);
			GridLayout layout= new GridLayout();
			composite.setLayout(layout);
			composite.setLayoutData(new GridData());
			setControl(composite);

			// set F1 help
			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.PATCH_OPTIONS_PAGE);

			Group diffTypeGroup = new Group(composite, SWT.NONE);
			layout = new GridLayout();
			diffTypeGroup.setLayout(layout);
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
			diffTypeGroup.setLayoutData(data);
			diffTypeGroup.setText(CVSUIMessages.Diff_output_format_12);

			unifiedDiffOption = new Button(diffTypeGroup, SWT.RADIO);
			unifiedDiffOption.setText(CVSUIMessages.Unified__format_required_by_Compare_With_Patch_feature__13);

			contextDiffOption = new Button(diffTypeGroup, SWT.RADIO);
			contextDiffOption.setText(CVSUIMessages.Context_14);
			regularDiffOption = new Button(diffTypeGroup, SWT.RADIO);
			regularDiffOption.setText(CVSUIMessages.Standard_15);

			diffTypeRadioGroup.add(FORMAT_UNIFIED, unifiedDiffOption);
			diffTypeRadioGroup.add(FORMAT_CONTEXT, contextDiffOption);
			diffTypeRadioGroup.add(FORMAT_STANDARD, regularDiffOption);

			//Unified Format Options
			Group unifiedGroup = new Group(composite, SWT.None);
			layout = new GridLayout();
			unifiedGroup.setLayout(layout);
			data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
			unifiedGroup.setLayoutData(data);
			unifiedGroup.setText(CVSUIMessages.GenerateDiffFileWizard_10);

			unified_workspaceRelativeOption = new Button(unifiedGroup, SWT.RADIO);
			unified_workspaceRelativeOption.setText(CVSUIMessages.GenerateDiffFileWizard_6);
			unified_workspaceRelativeOption.setSelection(true);

			unified_projectRelativeOption = new Button(unifiedGroup, SWT.RADIO);
			unified_projectRelativeOption.setText(CVSUIMessages.GenerateDiffFileWizard_7);

			unified_selectionRelativeOption = new Button(unifiedGroup, SWT.RADIO);
			unified_selectionRelativeOption.setText(CVSUIMessages.GenerateDiffFileWizard_8);

			unifiedRadioGroup.add(ROOT_WORKSPACE, unified_workspaceRelativeOption);
			unifiedRadioGroup.add(ROOT_PROJECT, unified_projectRelativeOption);
			unifiedRadioGroup.add(ROOT_SELECTION, unified_selectionRelativeOption);

			Dialog.applyDialogFont(parent);

			initializeDefaultValues();

			//add listeners
			unifiedDiffOption.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					setEnableUnifiedGroup(true);
					updateEnablements();
					diffTypeRadioGroup.setSelection(FORMAT_UNIFIED, false);
				}
			});

			contextDiffOption.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					setEnableUnifiedGroup(false);
					updateEnablements();
					diffTypeRadioGroup.setSelection(FORMAT_CONTEXT, false);
				}
			});

			regularDiffOption.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					setEnableUnifiedGroup(false);
					updateEnablements();
					diffTypeRadioGroup.setSelection(FORMAT_STANDARD, false);
				}
			});

			unified_workspaceRelativeOption
			.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					unifiedRadioGroup.setSelection(ROOT_WORKSPACE, false);
				}
			});

			unified_projectRelativeOption
			.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					unifiedRadioGroup.setSelection(ROOT_PROJECT, false);
				}
			});

			unified_selectionRelativeOption
			.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					unifiedRadioGroup.setSelection(ROOT_SELECTION, false);
				}
			});

			calculatePatchRoot();
			updateEnablements();

			// update selection
			diffTypeRadioGroup.selectEnabledOnly();
			unifiedRadioGroup.selectEnabledOnly();
		}

		public int getFormatSelection() {
			return diffTypeRadioGroup.getSelected();
		}

		public int getRootSelection() {
			return unifiedRadioGroup.getSelected();
		}

		private void initializeDefaultValues() {
			// Radio buttons for format
			diffTypeRadioGroup.setSelection(store.getFormatSelection(), true);
			// Radio buttons for patch root
			unifiedRadioGroup.setSelection(store.getRootSelection(), true);

			if (store.getFormatSelection() != FORMAT_UNIFIED) {
				setEnableUnifiedGroup(false);
			}
		}


		protected void updateEnablements() {
			if (!patchHasCommonRoot){
				diffTypeRadioGroup.setEnablement(false, new int[] {
						FORMAT_CONTEXT, FORMAT_STANDARD }, FORMAT_UNIFIED);
				unifiedRadioGroup.setEnablement(false, new int[] {
						ROOT_PROJECT, ROOT_SELECTION }, ROOT_WORKSPACE);
			}

			// temporary until we figure out best way to fix synchronize view
			// selection
			if (!unifiedSelectionEnabled)
				unifiedRadioGroup.setEnablement(false, new int[] {ROOT_SELECTION});
		}

		private void calculatePatchRoot(){
			//check to see if this is a multi select patch, if so disable
			IResource[] tempResources = ((GenerateDiffFileWizard)this.getWizard()).resources;

			//Guard for quick cancellation to avoid ArrayOutOfBounds (see Bug# 117234)
			if (tempResources == null)
				return;

			if (tempResources.length > 1){
				//Check to see is the selected resources are contained by the same parent (climbing
				//parent by parent to the project root)
				//If so, then allow selection relative patches -> set the relative path to the common
				//parent [also allow project relative patches]
				//If parents are different projects, allow only multiproject selection

				patchHasCommonRoot=true;
				int segmentMatch=-1;
				IPath path = tempResources[0].getFullPath().removeLastSegments(1);
				for (int i = 1; i < tempResources.length; i++) {
					int segments=path.matchingFirstSegments(tempResources[i].getFullPath());
					//Keep track of the lowest number of matches that were found - the common
					//path will be this number
					if (segmentMatch == -1 ||
							segmentMatch>segments){
						segmentMatch=segments;
					}
					//However, if no segments for any one resource - break out of the loop
					if (segments == 0){
						patchHasCommonRoot=false;
						break;
					}
				}
				if (patchHasCommonRoot){
					IPath tempPath = path.uptoSegment(segmentMatch);
					/*IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
					while (!root.exists(tempPath) &&
							!tempPath.isRoot()){
						tempPath = tempPath.removeLastSegments(1);
					}*/
					patchRoot=tempPath;
				}
			} else {
				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

				//take the file name off the path and use that as the patch root
				//patchRoot = tempResources[0].getFullPath().removeLastSegments(1);
				IPath fullPath = tempResources[0].getFullPath();
				IResource resource = root.findMember(fullPath);

				//keep trimming the path until we find something that can be used as the
				//patch root
				while (resource == null &&
						!(resource instanceof IWorkspaceRoot)){
					fullPath=fullPath.removeLastSegments(1);
					resource=root.findMember(fullPath);
				}
				patchRoot = resource.getFullPath();
				if (resource.getType() == IResource.FILE)
					patchRoot =resource.getFullPath().removeLastSegments(1);
			}
		}
		/**
		 * Return the list of Diff command options configured on this page.
		 */
		public LocalOption[] getOptions() {
			List<LocalOption> options = new ArrayList<>(5);
			/*  if(includeNewFilesOptions.getSelection()) {
				options.add(Diff.INCLUDE_NEWFILES);
			}
			if(!recurseOption.getSelection()) {
				options.add(Command.DO_NOT_RECURSE);
			}*/

			//Add new files for now
			options.add(Diff.INCLUDE_NEWFILES);

			if(unifiedDiffOption.getSelection()) {
				options.add(Diff.UNIFIED_FORMAT);
			} else if(contextDiffOption.getSelection()) {
				options.add(Diff.CONTEXT_FORMAT);
			}

			return options.toArray(new LocalOption[options.size()]);
		}
		protected void setEnableUnifiedGroup(boolean enabled){
			unifiedRadioGroup.setEnablement(enabled, new int[] {
					ROOT_WORKSPACE, ROOT_PROJECT, ROOT_SELECTION });

			//temporary until we figure out best way to fix synchronize view selection
			if (!unifiedSelectionEnabled)
				unifiedRadioGroup.setEnablement(false, new int[] {ROOT_SELECTION});
		}
	}

	/**
	 * Class to retrieve and store the default selected values.
	 */
	private final class DefaultValuesStore {

		private static final String PREF_LAST_SELECTION= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard.PatchFileSelectionPage.lastselection"; //$NON-NLS-1$
		private static final String PREF_LAST_FS_PATH= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard.PatchFileSelectionPage.filesystem.path"; //$NON-NLS-1$
		private static final String PREF_LAST_WS_PATH= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard.PatchFileSelectionPage.workspace.path"; //$NON-NLS-1$
		private static final String PREF_LAST_AO_FORMAT = "org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard.OptionsPage.diff.format"; //$NON-NLS-1$
		private static final String PREF_LAST_AO_ROOT = "org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard.OptionsPage.patch.root"; //$NON-NLS-1$


		private final IDialogSettings dialogSettings;

		public DefaultValuesStore() {
			dialogSettings= CVSUIPlugin.getPlugin().getDialogSettings();
		}

		public int getLocationSelection() {
			int value= LocationPage.CLIPBOARD;
			try {
				value= dialogSettings.getInt(PREF_LAST_SELECTION);
			} catch (NumberFormatException e) {
				// ignore
			}

			switch (value) {
			case LocationPage.FILESYSTEM:
			case LocationPage.WORKSPACE:
			case LocationPage.CLIPBOARD:
				return value;
			default:
				return LocationPage.CLIPBOARD;
			}
		}

		public String getFilesystemPath() {
			final String path= dialogSettings.get(PREF_LAST_FS_PATH);
			return path != null ? path : "";  //$NON-NLS-1$
		}

		public String getWorkspacePath() {
			final String path= dialogSettings.get(PREF_LAST_WS_PATH);
			return path != null ? path : ""; //$NON-NLS-1$
		}


		public int getFormatSelection() {
			int value = OptionsPage.FORMAT_UNIFIED;
			try {
				value = dialogSettings.getInt(PREF_LAST_AO_FORMAT);
			} catch (NumberFormatException e) {
			}

			switch (value) {
			case OptionsPage.FORMAT_UNIFIED:
			case OptionsPage.FORMAT_CONTEXT:
			case OptionsPage.FORMAT_STANDARD:
				return value;
			default:
				return OptionsPage.FORMAT_UNIFIED;
			}
		}

		public int getRootSelection() {
			int value = OptionsPage.ROOT_WORKSPACE;
			try {
				value = dialogSettings.getInt(PREF_LAST_AO_ROOT);
			} catch (NumberFormatException e) {
			}

			switch (value) {
			case OptionsPage.ROOT_WORKSPACE:
			case OptionsPage.ROOT_PROJECT:
			case OptionsPage.ROOT_SELECTION:
				return value;
			default:
				return OptionsPage.ROOT_WORKSPACE;
			}
		}

		public void storeLocationSelection(int defaultSelection) {
			dialogSettings.put(PREF_LAST_SELECTION, defaultSelection);
		}

		public void storeFilesystemPath(String path) {
			dialogSettings.put(PREF_LAST_FS_PATH, path);
		}

		public void storeWorkspacePath(String path) {
			dialogSettings.put(PREF_LAST_WS_PATH, path);
		}

		public void storeOutputFormat(int selection) {
			dialogSettings.put(PREF_LAST_AO_FORMAT, selection);
		}

		public void storePatchRoot(int selection) {
			dialogSettings.put(PREF_LAST_AO_ROOT, selection);
		}
	}

	private LocationPage locationPage;
	private OptionsPage optionsPage;

	protected IResource[] resources;
	private final DefaultValuesStore defaultValuesStore;
	private final IWorkbenchPart part;

	//temporary until we figure out best way to fix synchronize view selection
	protected boolean unifiedSelectionEnabled;

	public GenerateDiffFileWizard(IWorkbenchPart part, IResource[] resources, boolean unifiedSelectionEnabled) {
		super();
		this.part = part;
		this.resources = resources;
		setWindowTitle(CVSUIMessages.GenerateCVSDiff_title);
		initializeDefaultPageImageDescriptor();
		defaultValuesStore= new DefaultValuesStore();
		this.unifiedSelectionEnabled=unifiedSelectionEnabled;
	}

	@Override
	public void addPages() {
		String pageTitle = CVSUIMessages.GenerateCVSDiff_pageTitle;
		String pageDescription = CVSUIMessages.GenerateCVSDiff_pageDescription;
		locationPage = new LocationPage(pageTitle, pageTitle, CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_WIZBAN_DIFF), defaultValuesStore);
		locationPage.setDescription(pageDescription);
		addPage(locationPage);

		pageTitle = CVSUIMessages.Advanced_options_19;
		pageDescription = CVSUIMessages.Configure_the_options_used_for_the_CVS_diff_command_20;
		optionsPage = new OptionsPage(pageTitle, pageTitle, CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_WIZBAN_DIFF), defaultValuesStore);
		optionsPage.setDescription(pageDescription);
		addPage(optionsPage);
	}

	/**
	 * Declares the wizard banner iamge descriptor
	 */
	protected void initializeDefaultPageImageDescriptor() {
		final String iconPath= "icons/full/"; //$NON-NLS-1$
		try {
			final URL installURL = CVSUIPlugin.getPlugin().getBundle().getEntry("/"); //$NON-NLS-1$
			final URL url = new URL(installURL, iconPath + "wizards/newconnect_wiz.gif");	//$NON-NLS-1$
			ImageDescriptor desc = ImageDescriptor.createFromURL(url);
			setDefaultPageImageDescriptor(desc);
		} catch (MalformedURLException e) {
			// Should not happen.  Ignore.
		}
	}

	@Override
	public boolean needsProgressMonitor() {
		return true;
	}

	/**
	 * Completes processing of the wizard. If this method returns <code>
	 * true</code>, the wizard will close; otherwise, it will stay active.
	 */
	@Override
	public boolean performFinish() {

		final int location= locationPage.getSelectedLocation();

		final File file= location != LocationPage.CLIPBOARD? locationPage.getFile() : null;

		if (!(file == null || validateFile(file))) {
			return false;
		}

		//Is this a multi-patch?
		boolean multiPatch=false;
		if (optionsPage.unifiedDiffOption.getSelection() && optionsPage.unified_workspaceRelativeOption.getSelection())
			multiPatch=true;


		//If not a multipatch, patch should use project relative or selection relative paths[default]?
		boolean useProjectRelativePaths=false;
		if (optionsPage.unifiedDiffOption.getSelection() &&
				optionsPage.unified_projectRelativeOption.getSelection())
			useProjectRelativePaths=true;

		IFile binFile = locationPage.findBinaryFile();
		if (binFile != null) {
			int result = promptToIncludeBinary(binFile);
			if (result == 2)
				return false;
			if (result == 1)
				locationPage.removeBinaryFiles();
		}

		/**
		 * Perform diff operation.
		 */
		try {
			if (file != null) {
				generateDiffToFile(file,multiPatch,useProjectRelativePaths);
			} else {
				generateDiffToClipboard(multiPatch,useProjectRelativePaths);
			}
		} catch (TeamException e) {}

		/**
		 * Refresh workspace if necessary and save default selection.
		 */
		switch (location) {

		case LocationPage.WORKSPACE:
			final String workspaceResource= locationPage.getWorkspaceLocation();
			if (workspaceResource != null){
				defaultValuesStore.storeLocationSelection(LocationPage.WORKSPACE);
				defaultValuesStore.storeWorkspacePath(workspaceResource);
				/* try {
					workspaceResource.getParent().refreshLocal(IResource.DEPTH_ONE, null);
				} catch(CoreException e) {
					CVSUIPlugin.openError(getShell(), CVSUIMessages.GenerateCVSDiff_error, null, e);
					return false;
				} */
			} else {
				//Problem with workspace location, open with clipboard next time
				defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
			}
			break;

		case LocationPage.FILESYSTEM:
			defaultValuesStore.storeFilesystemPath(file.getPath());
			defaultValuesStore.storeLocationSelection(LocationPage.FILESYSTEM);
			break;

		case LocationPage.CLIPBOARD:
			defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
			break;

		default:
			return false;
		}


		/**
		 * Save default selections of Options Page
		 */

		defaultValuesStore.storeOutputFormat(optionsPage.getFormatSelection());
		defaultValuesStore.storePatchRoot(optionsPage.getRootSelection());

		return true;
	}

	private int promptToIncludeBinary(IFile file) {
		MessageDialog dialog = new MessageDialog(getShell(), CVSUIMessages.GenerateDiffFileWizard_11, null, // accept
				// the default window icon
				NLS.bind(CVSUIMessages.GenerateDiffFileWizard_12, file.getFullPath()), MessageDialog.WARNING, new String[] { IDialogConstants.YES_LABEL,
			IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 1); // no is the default
		return dialog.open();
	}

	private void generateDiffToClipboard(boolean multiPatch, boolean useProjectRelativePaths) throws TeamException {
		DiffOperation diffop = new ClipboardDiffOperation(part,RepositoryProviderOperation.asResourceMappers(resources, IResource.DEPTH_ZERO),optionsPage.getOptions(),multiPatch, useProjectRelativePaths, optionsPage.patchRoot);
		try {
			diffop.run();
		} catch (InvocationTargetException e) {}
		catch (InterruptedException e) {}
	}

	private void generateDiffToFile(File file, boolean multiPatch, boolean useProjectRelativePaths) throws TeamException {
		DiffOperation diffop = null;
		if (locationPage.selectedLocation == LocationPage.WORKSPACE){
			diffop = new WorkspaceFileDiffOperation(part,RepositoryProviderOperation.asResourceMappers(resources, IResource.DEPTH_ZERO),optionsPage.getOptions(),file, multiPatch, useProjectRelativePaths, optionsPage.patchRoot);
		}
		else {
			diffop = new FileDiffOperation(part,RepositoryProviderOperation.asResourceMappers(resources, IResource.DEPTH_ZERO),optionsPage.getOptions(),file, multiPatch, useProjectRelativePaths, optionsPage.patchRoot);
		}

		try {
			diffop.run();
		} catch (InvocationTargetException e) {}
		catch (InterruptedException e) {}
	}

	public boolean validateFile(File file) {

		if (file == null)
			return false;

		/**
		 * Consider file valid if it doesn't exist for now.
		 */
		if (!file.exists())
			return true;

		/**
		 * The file exists.
		 */
		if (!file.canWrite()) {
			final String title= CVSUIMessages.GenerateCVSDiff_1;
			final String msg= CVSUIMessages.GenerateCVSDiff_2;
			final MessageDialog dialog= new MessageDialog(getShell(), title, null, msg, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0);
			dialog.open();
			return false;
		}

		final String title = CVSUIMessages.GenerateCVSDiff_overwriteTitle;
		final String msg = CVSUIMessages.GenerateCVSDiff_overwriteMsg;
		final MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
		dialog.open();
		if (dialog.getReturnCode() != 0)
			return false;

		return true;
	}

	public LocationPage getLocationPage() {
		return locationPage;
	}

	/**
	 * The class maintain proper selection of radio button within the group:
	 * <ul>
	 * <li>Only one button can be selected at the time.</li>
	 * <li>Disabled button can't be selected unless all buttons in the group
	 * are disabled.</li>
	 * </ul>
	 */
	/*private*/ class RadioButtonGroup {

		/**
		 * List of buttons in the group. Both radio groups contain 3 elements.
		 */
		private List<Button> buttons = new ArrayList<>(3);

		/**
		 * Index of the selected button.
		 */
		private int selected = 0;

		/**
		 * Add a button to the group. While adding a new button the method
		 * checks if there is only one button selected in the group.
		 * 
		 * @param buttonCode
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
		 *            an index we need to subtract 1 from it.
		 * @param button
		 *            A button to add.
		 */
		public void add(int buttonCode, Button button) {
			if (button != null && (button.getStyle() & SWT.RADIO) != 0) {
				if (button.getSelection() && !buttons.isEmpty()) {
					deselectAll();
					selected = buttonCode - 1;
				}
				buttons.add(buttonCode - 1, button);
			}
		}

		/**
		 * Returns selected button's code.
		 * 
		 * @return Selected button's code.
		 */
		public int getSelected() {
			return selected + 1;
		}

		/**
		 * Set selection to the given button. When
		 * <code>selectEnabledOnly</code> flag is true the returned value can
		 * differ from the parameter when a button we want to set selection to
		 * is disabled and there are other buttons which are enabled.
		 * 
		 * @param buttonCode
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
		 *            an index we need to subtract 1 from it.
		 * @return Code of the button to which selection was finally set.
		 */
		public int setSelection(int buttonCode, boolean selectEnabledOnly) {
			deselectAll();

			buttons.get(buttonCode - 1).setSelection(true);
			selected = buttonCode - 1;
			if (selectEnabledOnly)
				selected = selectEnabledOnly() - 1;
			return getSelected();
		}

		/**
		 * Make sure that only an enabled radio button is selected.
		 * 
		 * @return A code of the selected button.
		 */
		public int selectEnabledOnly() {
			deselectAll();

			Button selectedButton = buttons.get(selected);
			if (!selectedButton.isEnabled()) {
				// if the button is disabled, set selection to an enabled one
				for (Iterator iterator = buttons.iterator(); iterator.hasNext();) {
					Button b = (Button) iterator.next();
					if (b.isEnabled()) {
						b.setSelection(true);
						selected = buttons.indexOf(b);
						return selected + 1;
					}
				}
				// if none found, reset the initial selection
				selectedButton.setSelection(true);
			} else {
				// because selection has been cleared, set it again
				selectedButton.setSelection(true);
			}
			// return selected button's code so the value can be stored
			return getSelected();
		}

		/**
		 * Enable or disable given buttons.
		 * 
		 * @param enabled
		 *            Indicates whether to enable or disable the buttons.
		 * @param buttonsToChange
		 *            Buttons to enable/disable.
		 * @param defaultSelection
		 *            The button to select if the currently selected button
		 *            becomes disabled.
		 */
		public void setEnablement(boolean enabled, int[] buttonsToChange,
				int defaultSelection) {

			// enable (or disable) given buttons
			for (int i = 0; i < buttonsToChange.length; i++) {
				this.buttons.get(buttonsToChange[i] - 1)
				.setEnabled(enabled);
			}
			// check whether the selected button is enabled
			if (!this.buttons.get(selected).isEnabled()) {
				if (defaultSelection != -1)
					// set the default selection and check if it's enabled
					setSelection(defaultSelection, true);
				else
					// no default selection is given, select any enabled button
					selectEnabledOnly();
			}
		}

		/**
		 * Enable or disable given buttons with no default selection. The selection
		 * will be set to an enabled button using the <code>selectEnabledOnly</code> method.
		 * 
		 * @param enabled Indicates whether to enable or disable the buttons.
		 * @param buttonsToChange Buttons to enable/disable.
		 */
		public void setEnablement(boolean enabled, int[] buttonsToChange) {
			// -1 means that no default selection is given
			setEnablement(enabled, buttonsToChange, -1);
		}

		/**
		 * Deselect all buttons in the group.
		 */
		private void deselectAll() {
			// clear all selections
			for (Iterator iterator = buttons.iterator(); iterator.hasNext();)
				((Button) iterator.next()).setSelection(false);
		}
	}

}
