/*******************************************************************************
 * 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
 *     Sebastian Davids <sdavids@gmx.de> - layout tweaks
 *     Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 180358 [Apply Patch] Cursor jumps to beginning of filename field on keystroke
 *******************************************************************************/
package org.eclipse.compare.internal.patch;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;

import org.eclipse.compare.internal.ICompareContextIds;
import org.eclipse.compare.internal.Utilities;
import org.eclipse.compare.patch.IFilePatch2;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;

import com.ibm.icu.text.MessageFormat;

public class InputPatchPage extends WizardPage {

	// constants
	protected static final int SIZING_TEXT_FIELD_WIDTH= 250;
	protected static final int COMBO_HISTORY_LENGTH= 5;

	// dialog store id constants
	private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$
	private final static String STORE_PATCH_FILES_ID= PAGE_NAME+".PATCH_FILES"; //$NON-NLS-1$
	private final static String STORE_PATCH_URLS_ID= PAGE_NAME+".PATCH_URLS"; //$NON-NLS-1$
	private final static String STORE_INPUT_METHOD_ID= PAGE_NAME+".INPUT_METHOD"; //$NON-NLS-1$
	private final static String STORE_WORKSPACE_PATH_ID= PAGE_NAME+".WORKSPACE_PATH"; //$NON-NLS-1$

	//patch input constants
	protected final static int CLIPBOARD= 1;
	protected final static int FILE= 2;
	protected final static int WORKSPACE= 3;
	protected final static int URL= 4;

	protected final static String INPUTPATCHPAGE_NAME= "InputPatchPage"; //$NON-NLS-1$

	private boolean fShowError= false;
	private String fPatchSource;
	private boolean fPatchRead= false;
	private PatchWizard fPatchWizard;
	private ActivationListener fActivationListener= new ActivationListener();

	// SWT widgets
	private Button fUseClipboardButton;
	private Combo fPatchFileNameField;
	private Button fPatchFileBrowseButton;
	private Button fUsePatchFileButton;
	private Button fUseWorkspaceButton;
	private Button fUseURLButton;
	private Combo fPatchURLField;
	private Label fWorkspaceSelectLabel;
	private TreeViewer fTreeViewer;

	class ActivationListener extends ShellAdapter {
		@Override
		public void shellActivated(ShellEvent e) {
			// allow error messages if the selected input actually has something selected in it
			fShowError=true;
			switch(getInputMethod()) {
			case FILE:
				fShowError= (fPatchFileNameField.getText() != "");  //$NON-NLS-1$
				break;
			case URL:
				fShowError = (fPatchURLField.getText() != ""); //$NON-NLS-1$
				break;
			case WORKSPACE:
				fShowError= (!fTreeViewer.getSelection().isEmpty());
				break;
			}
			updateWidgetEnablements();
		}
	}

	public InputPatchPage(PatchWizard pw) {
		super(INPUTPATCHPAGE_NAME, PatchMessages.InputPatchPage_title, null);
		fPatchWizard= pw;
		setMessage(PatchMessages.InputPatchPage_message);
	}

	/*
	 * Get a path from the supplied text widget.
	 * @return org.eclipse.core.runtime.IPath
	 */
	protected IPath getPathFromText(Text textField) {
		return (new Path(textField.getText())).makeAbsolute();
	}

	/* package */ String getPatchName() {
		if (getInputMethod() == CLIPBOARD)
			return PatchMessages.InputPatchPage_Clipboard;
		return getPatchFilePath();
	}

	@Override
	public void createControl(Composite parent) {

		Composite composite= new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout());
		composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
		setControl(composite);

		initializeDialogUnits(parent);

		buildPatchFileGroup(composite);

		// by default, whatever was used last was selected or
		// default to File if nothing has been selected
		restoreWidgetValues();

		// see if there are any better options presently selected (i.e workspace
		// or clipboard or URL from clipboard)
		adjustToCurrentTarget();

		// No error for dialog opening
		fShowError= false;
		clearErrorMessage();
		updateWidgetEnablements();

		Shell shell= getShell();
		shell.addShellListener(fActivationListener);

		Dialog.applyDialogFont(composite);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.PATCH_INPUT_WIZARD_PAGE);
	}

	/**
	 * Returns the next page depending on what type of patch is being applied:
	 * 	 i) If the patch is a Workspace patch then it will proceed right to the PreviewPatchPage
	 *  ii) If the patch is a single project patch then it will proceed to the PatchTargetPage, which
	 *      allows the user to specify where to root the patch
	 * @return PreviewPatchPage if multi-project patch, PatchTargetPage if single project patch
	 */
	@Override
	public IWizardPage getNextPage() {
		if (!checkPageComplete())
			return this;

		WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();

		// guess prefix count
		int guess= 0; // guessPrefix(diffs);
		patcher.setStripPrefixSegments(guess);

		// If this is a workspace patch we don't need to set a target as the targets will be figured out from
		// all of the projects that make up the patch and continue on to final preview page
		if (patcher.isWorkspacePatch()) {
			// skip 'Patch Target' page
			IWizardPage page = super.getNextPage();
			if (page.getName().equals(PatchTargetPage.PATCHTARGETPAGE_NAME))
				return page.getNextPage();
		}

		// If this is a git patch set the workspace root as the target and skip the target selection page
		if (patcher.isGitPatch()) {
			// skip 'Patch Target' page
			IWizardPage page = super.getNextPage();
			if (page.getName().equals(PatchTargetPage.PATCHTARGETPAGE_NAME)) {
				// set the workspace root as the target
				patcher.setTarget(ResourcesPlugin.getWorkspace().getRoot());
				return page.getNextPage();
			}
		}

		// else go on to target selection page
		return super.getNextPage();
	}

	boolean checkPageComplete() {
		WorkspacePatcher patcher= ((PatchWizard)getWizard()).getPatcher();

		// Read in the patch
		readInPatch();

		IFilePatch2[] diffs= patcher.getDiffs();
		if (diffs == null || diffs.length == 0) {
			String format= PatchMessages.InputPatchPage_NoDiffsFound_format;
			String message= MessageFormat.format(format, fPatchSource);
			MessageDialog.openInformation(null, PatchMessages.InputPatchPage_PatchErrorDialog_title, message);
			return false;
		}
		return true;
	}

	/*
	 * Reads in the patch contents
	 */
	public void readInPatch(){
		if (fPatchRead)
			return;

		WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();
		// Create a reader for the input
		Reader reader= null;
		try {
			int inputMethod= getInputMethod();
			if (inputMethod == CLIPBOARD) {
				Control c= getControl();
				if (c != null) {
					Clipboard clipboard= new Clipboard(c.getDisplay());
					Object o= clipboard.getContents(TextTransfer.getInstance());
					clipboard.dispose();
					if (o instanceof String)
						reader= new StringReader((String)o);
				}
				fPatchSource= PatchMessages.InputPatchPage_Clipboard_title;
			} else if (inputMethod==FILE) {
				String patchFilePath= getPatchFilePath();
				if (patchFilePath != null) {
					try {
						reader= new FileReader(patchFilePath);
					} catch (FileNotFoundException ex) {
						MessageDialog.openError(null,
							PatchMessages.InputPatchPage_PatchErrorDialog_title,
							PatchMessages.InputPatchPage_PatchFileNotFound_message);
					}
				}
				fPatchSource= PatchMessages.InputPatchPage_PatchFile_title;
			} else if (inputMethod==URL) {
				String patchFileURL = fPatchURLField.getText();
				if (patchFileURL != null) {
					try {
						String contents = Utilities.getURLContents(new URL(
								patchFileURL), getContainer());
						if (contents != null)
							reader = new StringReader(contents);
					} catch (MalformedURLException | InvocationTargetException | OperationCanceledException | InterruptedException e) { // ignore
					}
				}
				fPatchSource= PatchMessages.InputPatchPage_URL_title;
			} else if (inputMethod==WORKSPACE) {
				// Get the selected patch file (tree will only allow for one selection)
				IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
				IResource patchFile= resources[0];
				if (patchFile != null) {
					if (patchFile.getLocation() == null) {
						MessageDialog.openError(null, PatchMessages.InputPatchPage_PatchErrorDialog_title, PatchMessages.InputPatchPage_PatchFileNotFound_message);
					} else {
						try {
							reader = new FileReader(patchFile.getLocation().toFile());
						} catch (FileNotFoundException ex) {
							MessageDialog.openError(null, PatchMessages.InputPatchPage_PatchErrorDialog_title,
									PatchMessages.InputPatchPage_PatchFileNotFound_message);
						}
					}
				}
				fPatchSource= PatchMessages.InputPatchPage_WorkspacePatch_title;
			}

			// parse the input
			if (reader != null) {
				try {
					patcher.parse(new BufferedReader(reader));
					//report back to the patch wizard that the patch has been read in
					fPatchWizard.patchReadIn();
					fPatchRead=true;
				} catch (Exception ex) {
					// Ignore. User will be informed of error since patcher contains no diffs
					setPageComplete(false);
				}
			}
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException x) {
					// silently ignored
				}
			}
		}
	}

	@Override
	public boolean canFlipToNextPage() {
		// we can't call getNextPage to determine if flipping is allowed since computing
		// the next page is quite expensive. So we say yes if the page is complete.
		return isPageComplete();
	}

	private void setEnablePatchFile(boolean enable) {
		fPatchFileNameField.setEnabled(enable);
		fPatchFileBrowseButton.setEnabled(enable);
	}

	private void setEnableWorkspacePatch(boolean enable) {
		fWorkspaceSelectLabel.setEnabled(enable);
		fTreeViewer.getTree().setEnabled(enable);
	}

	private void setEnableURLPatch(boolean enable) {
		fPatchURLField.setEnabled(enable);
	}

	/*
	 *	Create the group for selecting the patch file
	 */
	private void buildPatchFileGroup(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));

		// 1st row
		GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
		gd.horizontalSpan= 3;
		fUseClipboardButton= new Button(composite, SWT.RADIO);
		fUseClipboardButton.setText(PatchMessages.InputPatchPage_UseClipboardButton_text);
		fUseClipboardButton.setLayoutData(gd);

		// 2nd row
		fUsePatchFileButton= new Button(composite, SWT.RADIO);
		fUsePatchFileButton.setText(PatchMessages.InputPatchPage_FileButton_text);

		fPatchFileNameField= new Combo(composite, SWT.BORDER);
		gd= new GridData(GridData.FILL_HORIZONTAL);
		gd.widthHint= SIZING_TEXT_FIELD_WIDTH;
		fPatchFileNameField.setLayoutData(gd);

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

		//3rd row
		fUseURLButton = new Button(composite, SWT.RADIO);
		fUseURLButton.setText(PatchMessages.InputPatchPage_URLButton_text);

		fPatchURLField = new Combo(composite, SWT.BORDER);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 2;
		fPatchURLField.setLayoutData(gd);

		//4th row
		fUseWorkspaceButton= new Button(composite, SWT.RADIO);
		fUseWorkspaceButton.setText(PatchMessages.InputPatchPage_UseWorkspaceButton_text);
		gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
		fUseWorkspaceButton.setLayoutData(gd);

		addWorkspaceControls(parent);

		// Add listeners
		fUseClipboardButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!fUseClipboardButton.getSelection())
					return;

				clearErrorMessage();
				fShowError= true;
				int state= getInputMethod();
				setEnablePatchFile(state == FILE);
				setEnableURLPatch(state == URL);
				setEnableWorkspacePatch(state == WORKSPACE);
				updateWidgetEnablements();
				fPatchRead = false;
			}
		});

		fUsePatchFileButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!fUsePatchFileButton.getSelection())
					return;
				//If there is anything typed in at all
				clearErrorMessage();
				fShowError= (fPatchFileNameField.getText() != ""); //$NON-NLS-1$
				int state= getInputMethod();
				setEnablePatchFile(state == FILE);
				setEnableURLPatch(state == URL);
				setEnableWorkspacePatch(state == WORKSPACE);
				updateWidgetEnablements();
				fPatchRead = false;
			}
		});
		fPatchFileNameField.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateWidgetEnablements();
			}
		});
		fPatchFileNameField.addModifyListener(e -> {
			clearErrorMessage();
			fShowError= true;
			fPatchRead = false;
			updateWidgetEnablements();
		});
		fPatchFileBrowseButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				clearErrorMessage();
				fShowError= true;
				handlePatchFileBrowseButtonPressed();
				updateWidgetEnablements();
			}
		});
		fUseURLButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				clearErrorMessage();
				fShowError= (fPatchURLField.getText() != ""); //$NON-NLS-1$
				int state= getInputMethod();
				setEnablePatchFile(state == FILE);
				setEnableURLPatch(state == URL);
				setEnableWorkspacePatch(state == WORKSPACE);
				updateWidgetEnablements();
			}
		});
		fPatchURLField.addModifyListener(e -> {
			clearErrorMessage();
			fShowError = true;
			fPatchRead = false;
			updateWidgetEnablements();
		});
		fUseWorkspaceButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!fUseWorkspaceButton.getSelection())
					return;
				clearErrorMessage();
				// If there is anything typed in at all
				fShowError= (!fTreeViewer.getSelection().isEmpty());
				int state= getInputMethod();
				setEnablePatchFile(state == FILE);
				setEnableURLPatch(state == URL);
				setEnableWorkspacePatch(state == WORKSPACE);
				updateWidgetEnablements();
				fPatchRead = false;
			}
		});

		fTreeViewer.addSelectionChangedListener(event -> {
			clearErrorMessage();
			updateWidgetEnablements();
		});

		fTreeViewer.addDoubleClickListener(event -> {
			ISelection selection= event.getSelection();
			if (selection instanceof TreeSelection) {
				TreeSelection treeSel= (TreeSelection) selection;
				Object res= treeSel.getFirstElement();
				if (res != null) {
					if (res instanceof IProject || res instanceof IFolder) {
						if (fTreeViewer.getExpandedState(res))
							fTreeViewer.collapseToLevel(res, 1);
						else
							fTreeViewer.expandToLevel(res, 1);
					} else if (res instanceof IFile)
						fPatchWizard.showPage(getNextPage());
				}
			}
		});
	}

	private void addWorkspaceControls(Composite composite) {

		Composite newComp= new Composite(composite, SWT.NONE);
		GridLayout layout= new GridLayout(1, false);
		layout.marginLeft= 16; // align w/ lable of check button
		newComp.setLayout(layout);
		newComp.setLayoutData(new GridData(GridData.FILL_BOTH));

		fWorkspaceSelectLabel= new Label(newComp, SWT.LEFT);
		fWorkspaceSelectLabel.setText(PatchMessages.InputPatchPage_WorkspaceSelectPatch_text);

		fTreeViewer= new TreeViewer(newComp, SWT.BORDER);
		GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
		layoutData.heightHint = 300;
		fTreeViewer.getTree().setLayoutData(layoutData);

		fTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
		fTreeViewer.setContentProvider(new WorkbenchContentProvider());
		fTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
		fTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
	}


	/**
	 * Updates the enable state of this page's controls.
	 */
	private void updateWidgetEnablements() {

		String error= null;

		boolean gotPatch= false;
		int inputMethod= getInputMethod();
		if (inputMethod==CLIPBOARD) {
			Control c= getControl();
			if (c != null) {
				Clipboard clipboard= new Clipboard(c.getDisplay());
				Object o= clipboard.getContents(TextTransfer.getInstance());
				clipboard.dispose();
				if (o instanceof String) {
					String s= ((String) o).trim();
					if (s.length() > 0)
						gotPatch= true;
					else
						error= PatchMessages.InputPatchPage_ClipboardIsEmpty_message;
				} else
					error= PatchMessages.InputPatchPage_NoTextInClipboard_message;
			} else
				error= PatchMessages.InputPatchPage_CouldNotReadClipboard_message;
		} else if (inputMethod==FILE) {
			String path= fPatchFileNameField.getText();
			if (path != null && path.length() > 0) {
				File file= new File(path);
				gotPatch= file.exists() && file.isFile() && file.length() > 0;
				if (!gotPatch)
					error= PatchMessages.InputPatchPage_CannotLocatePatch_message + path;
			} else {
				error= PatchMessages.InputPatchPage_NoFileName_message;
			}
		} else if (inputMethod == URL) {
			String urlText = fPatchURLField.getText();
			if(urlText != null) {
				try {
					new URL(urlText);
					// Checking the URL is a bit too heavy for each keystroke.
					// Let's assume it contains a valid patch.
					gotPatch = true;
				} catch (MalformedURLException e) {
					error= PatchMessages.InputPatchPage_MalformedURL;
				}
			} else {
				error= PatchMessages.InputPatchPage_NoURL;
			}
		} else if (inputMethod == WORKSPACE) {
			//Get the selected patch file (tree will only allow for one selection)
			IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
			if (resources != null && resources.length > 0) {
				IResource patchFile= resources[0];
				if (patchFile != null && patchFile.getType() == IResource.FILE) {
					IPath location = patchFile.getLocation();
					if (location == null) {
						error = PatchMessages.InputPatchPage_PatchFileNotFound_message;
					} else {
						File actualFile= location.toFile();
						gotPatch= actualFile.exists()&&actualFile.isFile()&&actualFile.length() > 0;
						if (!gotPatch)
							error= PatchMessages.InputPatchPage_FileSelectedNotPatch_message;
					}
				}
			} else {
				error= PatchMessages.InputPatchPage_NoFileName_message;
			}
		}

		setPageComplete(gotPatch);

		if (fShowError)
			setErrorMessage(error);
	}

	protected void handlePatchFileBrowseButtonPressed() {
		FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
		dialog.setText(PatchMessages.InputPatchPage_SelectPatchFileDialog_title);
		String patchFilePath= getPatchFilePath();
		if (patchFilePath != null) {
			int lastSegment= patchFilePath.lastIndexOf(File.separatorChar);
			if (lastSegment > 0) {
				patchFilePath= patchFilePath.substring(0, lastSegment);
			}
		}
		dialog.setFilterPath(patchFilePath);
		String res= dialog.open();
		if (res == null)
			return;

		patchFilePath= dialog.getFileName();
		IPath filterPath= new Path(dialog.getFilterPath());
		IPath path= filterPath.append(patchFilePath).makeAbsolute();
		patchFilePath= path.toOSString();
		//fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());

		fPatchFileNameField.setText(patchFilePath);
		//setSourceName(patchFilePath);
	}

	/**
	 * Sets the source name of the import to be the supplied path.
	 * Adds the name of the path to the list of items in the
	 * source combo and selects it.
	 *
	 * @param path the path to be added
	 */
	protected void setSourceName(String path) {

		if (path.length() > 0) {

			String[] currentItems= fPatchFileNameField.getItems();
			int selectionIndex= -1;
			for (int i= 0; i < currentItems.length; i++)
				if (currentItems[i].equals(path))
					selectionIndex= i;

			if (selectionIndex < 0) {	// not found in history
				int oldLength= currentItems.length;
				String[] newItems= new String[oldLength + 1];
				System.arraycopy(currentItems, 0, newItems, 0, oldLength);
				newItems[oldLength]= path;
				fPatchFileNameField.setItems(newItems);
				selectionIndex= oldLength;
			}
			fPatchFileNameField.select(selectionIndex);

			//resetSelection();
		}
	}

	/**
	 *	The Finish button was pressed. Try to do the required work now and answer
	 *	a boolean indicating success. If false is returned then the wizard will
	 *	not close.
	 *
	 * @return boolean
	 */
	public boolean finish() {
//		if (!ensureSourceIsValid())
//			return false;

		saveWidgetValues();

//		Iterator resourcesEnum= getSelectedResources().iterator();
//		List fileSystemObjects= new ArrayList();
//		while (resourcesEnum.hasNext()) {
//			fileSystemObjects.add(
//				((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
//		}
//
//		if (fileSystemObjects.size() > 0)
//			return importResources(fileSystemObjects);
//
//		MessageDialog
//			.openInformation(
//				getContainer().getShell(),
//				DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
//				DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
//
//		return false;

		return true;
	}

	/**
	 *	Use the dialog store to restore widget values to the values that they held
	 *	last time this wizard was used to completion
	 */
	private void restoreWidgetValues() {

		int inputMethod= FILE;

		IDialogSettings settings= getDialogSettings();
		if (settings != null) {

			try {
				inputMethod= settings.getInt(STORE_INPUT_METHOD_ID);
			} catch (NumberFormatException ex) {
				//OK - no value stored in settings; just use CLIPBOARD
			}

			// set filenames history
			String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
			if (sourceNames != null)
				for (String sourceName : sourceNames) {
					if (sourceName != null && sourceName.length() > 0) {
						fPatchFileNameField.add(sourceName);
					}
				}

			// set patch file path
			String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
			if (patchFilePath != null)
				setSourceName(patchFilePath);

			// set URLs history
			String[] sourceURLs= settings.getArray(STORE_PATCH_URLS_ID);
			if (sourceURLs != null)
				for (String sourceURL : sourceURLs) {
					if (sourceURL != null && sourceURL.length() > 0) {
						fPatchURLField.add(sourceURL);
					}
				}

			// If the previous apply patch was used with a clipboard, we need to check
			// if there is a valid patch on the clipboard. This will be done in adjustToCurrentTarget()
			// so just set it to FILE now and, if there exists a patch on the clipboard, then clipboard
			// will be selected automatically
			if (inputMethod == CLIPBOARD){
				inputMethod= FILE;
				fPatchFileNameField.deselectAll();
			}

			//set the workspace patch selection
			String workspaceSetting= settings.get(STORE_WORKSPACE_PATH_ID);
			if (workspaceSetting != null && workspaceSetting.length() > 0) {
				// See if this resource still exists in the workspace
				try {
					IPath path= new Path(workspaceSetting);
					IFile targetFile= ResourcesPlugin.getWorkspace().getRoot().getFile(path);
					if (fTreeViewer != null && targetFile.exists()){
						fTreeViewer.expandToLevel(targetFile, 0);
						fTreeViewer.setSelection(new StructuredSelection(targetFile));
					}
				} catch (RuntimeException e) {
					// Ignore. The setting was invalid
				}
			} else {
				//check to see if the current input is set to workspace - if it is switch it
				//back to clipboard since there is no corresponding element to go along with
				//the tree viewer
				if (inputMethod == WORKSPACE)
					inputMethod= FILE;
			}
		}

		// set radio buttons state
		setInputButtonState(inputMethod);
	}

	/**
	 * 	Since Finish was pressed, write widget values to the dialog store so that they
	 *	will persist into the next invocation of this wizard page
	 */
	void saveWidgetValues() {
		IDialogSettings settings= getDialogSettings();
		if (settings != null) {

			settings.put(STORE_INPUT_METHOD_ID, getInputMethod());
			settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());

			// update source names history
			String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
			if (sourceNames == null)
				sourceNames= new String[0];

			sourceNames= addToHistory(sourceNames, getPatchFilePath());
			settings.put(STORE_PATCH_FILES_ID, sourceNames);

			// update source URLs history
			String[] sourceURLs= settings.getArray(STORE_PATCH_URLS_ID);
			if (sourceURLs == null)
				sourceURLs= new String[0];

			sourceURLs= addToHistory(sourceURLs, fPatchURLField.getText());
			settings.put(STORE_PATCH_URLS_ID, sourceURLs);

			// save the workspace selection
			settings.put(STORE_WORKSPACE_PATH_ID, getWorkspacePath());

		}
	}

	private String getWorkspacePath() {
		if (fTreeViewer != null){
			IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
			if (resources.length > 0) {
				IResource patchFile= resources[0];
				return patchFile.getFullPath().toString();
			}

		}
		return ""; //$NON-NLS-1$
	}

	// static helpers

	/**
	 * Checks to see if the file that has been selected for Apply Patch is
	 * actually a patch
	 *
	 * @return true if the file selected to run Apply Patch on in the workspace
	 *         is a patch file or if the clipboard contains a patch or if the
	 *         clipboard contains an URL (we assume it points to a patch )
	 */
	private boolean adjustToCurrentTarget() {
		// readjust selection if there is a patch selected in the workspace or on the clipboard
		// check workspace first
		IResource patchTarget= fPatchWizard.getTarget();
		if (patchTarget instanceof IFile && patchTarget.getLocation() != null) {
			Reader reader= null;
			try {
				try {
					reader= new FileReader(patchTarget.getLocation().toFile());
					if (isPatchFile(reader)) {
						// set choice to workspace
						setInputButtonState(WORKSPACE);
						if (fTreeViewer != null && patchTarget.exists()) {
							fTreeViewer.expandToLevel(patchTarget, 0);
							fTreeViewer.setSelection(new StructuredSelection(patchTarget));
						}
						return true;
					}
				} catch (FileNotFoundException ex) {
					// silently ignored
				}
			} finally {
				if (reader != null) {
					try {
						reader.close();
					} catch (IOException x) {
						// silently ignored
					}
				}
			}
		}
		// check out clipboard contents
		Reader reader = null;
		Control c = getControl();
		if (c != null) {
			Clipboard clipboard= new Clipboard(c.getDisplay());
			Object o= clipboard.getContents(TextTransfer.getInstance());
			clipboard.dispose();
			try {
				if (o instanceof String) {
					reader= new StringReader((String) o);
					if (isPatchFile(reader)) {
						setInputButtonState(CLIPBOARD);
						return true;
					}
					// maybe it's an URL
					try {
						new URL((String)o);
						setInputButtonState(URL);
						fPatchURLField.setText((String)o);
						return true;
					} catch (MalformedURLException e) {
						// ignore
					}
				}
			} finally {
				if (reader != null) {
					try {
						reader.close();
					} catch (IOException x) {
						// silently ignored
					}
				}
			}
		}
		return false;
	}

	private boolean isPatchFile(Reader reader) {
		WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();

		try {
			patcher.parse(new BufferedReader(reader));
		} catch (Exception ex) {
			return false;
		}

		IFilePatch2[] diffs= patcher.getDiffs();
		if (diffs == null || diffs.length == 0)
			return false;
		return true;
	}

	/*
	 * Clears the dialog message box
	 */
	private void clearErrorMessage(){
		setErrorMessage(null);
	}

	private void setInputButtonState(int state) {

		switch (state) {
		case CLIPBOARD:
			fUseClipboardButton.setSelection(true);
			fUsePatchFileButton.setSelection(false);
			fUseURLButton.setSelection(false);
			fUseWorkspaceButton.setSelection(false);
			break;

		case FILE:
			fUseClipboardButton.setSelection(false);
			fUsePatchFileButton.setSelection(true);
			fUseURLButton.setSelection(false);
			fUseWorkspaceButton.setSelection(false);
			break;

		case URL:
			fUseClipboardButton.setSelection(false);
			fUsePatchFileButton.setSelection(false);
			fUseURLButton.setSelection(true);
			fUseWorkspaceButton.setSelection(false);
			break;

		case WORKSPACE:
			fUseClipboardButton.setSelection(false);
			fUsePatchFileButton.setSelection(false);
			fUseURLButton.setSelection(false);
			fUseWorkspaceButton.setSelection(true);
			break;
		}

		setEnablePatchFile(state == FILE);
		setEnableWorkspacePatch(state == WORKSPACE);
		setEnableURLPatch(state == URL);
	}

	protected int getInputMethod() {
		if (fUseClipboardButton.getSelection())
			return CLIPBOARD;
		if (fUsePatchFileButton.getSelection())
			return FILE;
		if(fUseURLButton.getSelection())
			return URL;
		return WORKSPACE;
	}

	private String getPatchFilePath() {
		if (fPatchFileNameField != null)
			return fPatchFileNameField.getText();
		return ""; //$NON-NLS-1$
	}

	/*
	 * Adds an entry to a history, while taking care of duplicate history items
	 * and excessively long histories. The assumption is made that all histories
	 * should be of length <code>COMBO_HISTORY_LENGTH</code>.
	 *
	 * @param history the current history
	 * @param newEntry the entry to add to the history
	 */
	protected static String[] addToHistory(String[] history, String newEntry) {
		ArrayList<String> l= new ArrayList<>(Arrays.asList(history));

		l.remove(newEntry);
		l.add(0,newEntry);

		// since only one new item was added, we can be over the limit
		// by at most one item
		if (l.size() > COMBO_HISTORY_LENGTH)
			l.remove(COMBO_HISTORY_LENGTH);

		return l.toArray(new String[l.size()]);
	}

	public boolean isPatchRead() {
		return fPatchRead;
	}
}

