/*******************************************************************************
 * Copyright (c) 2000, 2020 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
 * Willian Mitsuda <wmitsuda@gmail.com>
 *    - Fix for bug 196553 - [Dialogs] Support IColorProvider/IFontProvider in FilteredItemsSelectionDialog
 * Peter Friese <peter.friese@gentleware.com>
 *    - Fix for bug 208602 - [Dialogs] Open Type dialog needs accessible labels
 * Simon Muschel <smuschel@gmx.de> - bug 258493
 * Kris De Volder Copied and modified from org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog
 *                to create QuickSearchDialog
 *******************************************************************************/
package org.eclipse.text.quicksearch.internal.ui;

import static org.eclipse.jface.resource.JFaceResources.TEXT_FONT;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ILazyContentProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.osgi.util.NLS;
import org.eclipse.search.internal.ui.text.EditorOpener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.text.quicksearch.internal.core.LineItem;
import org.eclipse.text.quicksearch.internal.core.QuickTextQuery;
import org.eclipse.text.quicksearch.internal.core.QuickTextQuery.TextRange;
import org.eclipse.text.quicksearch.internal.core.QuickTextSearchRequestor;
import org.eclipse.text.quicksearch.internal.core.QuickTextSearcher;
import org.eclipse.text.quicksearch.internal.core.pathmatch.ResourceMatchers;
import org.eclipse.text.quicksearch.internal.util.DocumentFetcher;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.progress.UIJob;

/**
 * Shows a list of items to the user with a text entry field for a string
 * pattern used to filter the list of items.
 *
 * @since 3.3
 */
@SuppressWarnings({ "rawtypes", "restriction", "unchecked" })
public class QuickSearchDialog extends SelectionStatusDialog {

	private static final int OPEN_BUTTON_ID = IDialogConstants.OK_ID;
	private static final int REFRESH_BUTTON_ID = IDialogConstants.RETRY_ID;

	public static final Styler HIGHLIGHT_STYLE = org.eclipse.search.internal.ui.text.DecoratingFileSearchLabelProvider.HIGHLIGHT_STYLE;

	private UIJob refreshJob = new UIJob(Messages.QuickSearchDialog_RefreshJob) {
		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			refreshWidgets();
			return Status.OK_STATUS;
		}
	};

	protected void openSelection() {
		try {
			LineItem item = (LineItem) this.getFirstResult();
			if (item!=null) {
				QuickTextQuery q = this.getQuery();
				TextRange range = q.findFirst(item.getText());
				EditorOpener opener = new EditorOpener();
				IWorkbenchPage page = window.getActivePage();
				if (page!=null) {
					opener.openAndSelect(page, item.getFile(), range.getOffset()+item.getOffset(),
						range.getLength(), true);
				}
			}
		} catch (PartInitException e) {
			QuickSearchActivator.log(e);
		}
	}

	/**
	 * Job that shows a simple busy indicator while a search is active.
	 * The job must be scheduled when a search starts/resumes.
	 */
	private UIJob progressJob =  new UIJob(Messages.QuickSearchDialog_RefreshJob) {
		int animate = 0; // number of dots to display.

		protected String dots(int animate) {
			char[] chars = new char[animate];
			for (int i = 0; i < chars.length; i++) {
				chars[i] = '.';
			}
			return new String(chars);
		}

		protected String currentFileInfo(IFile currentFile, int animate) {
			if (currentFile!=null) {
				String path = currentFile.getFullPath().toString();
				if (path.length()<=30) {
					return path;
				}
				return "..."+path.substring(path.length()-30); //$NON-NLS-1$
			}
			return dots(animate);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor mon) {
			if (!mon.isCanceled() && progressLabel!=null && !progressLabel.isDisposed()) {
				if (searcher==null || !searcher.isActive()) {
					progressLabel.setText(EMPTY_STRING);
				} else {
					progressLabel.setText(NLS.bind(Messages.QuickSearchDialog_searching, currentFileInfo(searcher.getCurrentFile(), animate)));
					animate = (animate+1)%4;
					this.schedule(333);
				}
			}
			return Status.OK_STATUS;
		}
	};

	public final StyledCellLabelProvider LINE_NUMBER_LABEL_PROVIDER = new StyledCellLabelProvider() {
		@Override
		public void update(ViewerCell cell) {
			LineItem item = (LineItem) cell.getElement();
			if (item!=null) {
				cell.setText(Integer.toString(item.getLineNumber()));
			} else {
				cell.setText("?"); //$NON-NLS-1$
			}
			cell.setImage(getBlankImage());
		};
	};

	private static final Color GREY = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY);

	private final StyledCellLabelProvider LINE_TEXT_LABEL_PROVIDER = new StyledCellLabelProvider() {

		@Override
		public void update(ViewerCell cell) {
			LineItem item = (LineItem) cell.getElement();
			if (item!=null) {
				StyledString text = highlightMatches(item.getText());
				cell.setText(text.getString());
				cell.setStyleRanges(text.getStyleRanges());
			} else {
				cell.setText(EMPTY_STRING);
				cell.setStyleRanges(null);
			}
			cell.setImage(getBlankImage());
			super.update(cell);
		}
	};

	private Image blankImage;

	private Image getBlankImage() {
		if (blankImage==null) {
			blankImage = new Image(Display.getDefault(), 1, 1);
//			GC gc = new GC(blankImage);
//			gc.fillRectangle(0, 0, 16, 16);
//			gc.dispose();
		}
		return blankImage;
	}

	private final StyledCellLabelProvider LINE_FILE_LABEL_PROVIDER = new StyledCellLabelProvider() {

		@Override
		public void update(ViewerCell cell) {
			LineItem item = (LineItem) cell.getElement();
			if (item!=null) {
				IPath path = item.getFile().getFullPath();
				String name = path.lastSegment();
				String dir = path.removeLastSegments(1).toString();
				if (dir.startsWith("/")) { //$NON-NLS-1$
					dir = dir.substring(1);
				}
				cell.setText(name + " - " + dir); //$NON-NLS-1$
				StyleRange[] styleRanges = new StyleRange[] {
						new StyleRange(name.length(), dir.length()+3, GREY, null)
				};
				cell.setStyleRanges(styleRanges);
			} else {
				cell.setText(EMPTY_STRING);
				cell.setStyleRanges(null);
			}
			cell.setImage(getBlankImage());
			super.update(cell);
		}

//		public String getToolTipText(Object element) {
//			LineItem item = (LineItem) element;
//			if (item!=null) {
//				return ""+item.getFile().getFullPath();
//			}
//			return "";
//		};

//		public String getText(Object _item) {
//			if (_item!=null) {
//				LineItem item = (LineItem) _item;
//				return item.getFile().getName().toString();
//			}
//			return "?";
//		};
	};

	private static final String DIALOG_SETTINGS = QuickSearchDialog.class.getName()+".DIALOG_SETTINGS"; //$NON-NLS-1$

	private static final String DIALOG_BOUNDS_SETTINGS = "DialogBoundsSettings"; //$NON-NLS-1$

	private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
	private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
	private static final String DIALOG_COLUMNS = "COLUMN_WIDTHS"; //$NON-NLS-1$
	private static final String DIALOG_SASH_WEIGHTS = "SASH_WEIGHTS"; //$NON-NLS-1$

	private static final String DIALOG_LAST_QUERY = "LAST_QUERY"; //$NON-NLS-1$
	private static final String DIALOG_PATH_FILTER = "PATH_FILTER"; //$NON-NLS-1$
	private static final String CASE_SENSITIVE = "CASE_SENSITIVE"; //$NON-NLS-1$
	private static final boolean CASE_SENSITIVE_DEFAULT = true;

	private static final String KEEP_OPEN = "KEEP_OPEN"; //$NON-NLS-1$
	private static final boolean KEEP_OPEN_DEFAULT = false;

	/**
	 * Represents an empty selection in the pattern input field (used only for
	 * initial pattern).
	 */
	public static final int NONE = 0;

	/**
	 * Pattern input field selection where caret is at the beginning (used only
	 * for initial pattern).
	 */
	public static final int CARET_BEGINNING = 1;

	/**
	 * Represents a full selection in the pattern input field (used only for
	 * initial pattern).
	 */
	public static final int FULL_SELECTION = 2;

	private Text pattern;

	private TableViewer list;

	private MenuManager menuManager;

	private MenuManager contextMenuManager;

	private boolean multi;

	private ToolBar toolBar;

	private ToolItem toolItem;

	private Label progressLabel;

	private ContentProvider contentProvider;

	private String initialPatternText;

	private int selectionMode;

	private static final String EMPTY_STRING = ""; //$NON-NLS-1$

	private final int MAX_LINE_LEN;

	private IHandlerActivation showViewHandler;

	private QuickTextSearcher searcher;

	private StyledText details;

	private DocumentFetcher documents;


	private ToggleCaseSensitiveAction toggleCaseSensitiveAction;
	private ToggleKeepOpenAction toggleKeepOpenAction;


	private QuickSearchContext context;


	private SashForm sashForm;

	private Label headerLabel;

	private IWorkbenchWindow window;
	private Text searchIn;

	/**
	 * Creates a new instance of the class.
	 *
	 * @param window.getShell()
	 *           shell to parent the dialog on
	 * @param multi
	 *           indicates whether dialog allows to select more than one
	 *           position in its list of items
	 */
	public QuickSearchDialog(IWorkbenchWindow window) {
		super(window.getShell());
		this.window = window;
		setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE | SWT.RESIZE);
		setBlockOnOpen(false);
		this.setTitle(Messages.QuickSearchDialog_title);
		this.context = new QuickSearchContext(window);
		this.multi = false;
		contentProvider = new ContentProvider();
		selectionMode = NONE;
		MAX_LINE_LEN = QuickSearchActivator.getDefault().getPreferences().getMaxLineLen();
		progressJob.setSystem(true);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jface.window.Window#create()
	 */
	@Override
	public void create() {
		super.create();
		pattern.setFocus();
	}

	/**
	 * Restores dialog using persisted settings.
	 */
	protected void restoreDialog(IDialogSettings settings) {
		try {
			if (initialPatternText==null) {
				String lastSearch = settings.get(DIALOG_LAST_QUERY);
				if (lastSearch==null) {
					lastSearch = EMPTY_STRING;
				}
				pattern.setText(lastSearch);
				pattern.selectAll();
			}
			if (settings.get(DIALOG_PATH_FILTER)!=null) {
				String filter = settings.get(DIALOG_PATH_FILTER);
				searchIn.setText(filter);
			}

			if (settings.getArray(DIALOG_COLUMNS)!=null) {
				String[] columnWidths = settings.getArray(DIALOG_COLUMNS);
				Table table = list.getTable();
				int cols = table.getColumnCount();
				for (int i = 0; i < cols; i++) {
					TableColumn col = table.getColumn(i);
					try {
						if (col!=null) {
							col.setWidth(Integer.valueOf(columnWidths[i]));
						}
					} catch (Throwable e) {
						QuickSearchActivator.log(e);
					}
				}
			}

			if (settings.getArray(DIALOG_SASH_WEIGHTS)!=null) {
				String[] _weights = settings.getArray(DIALOG_SASH_WEIGHTS);
				int[] weights = new int[_weights.length];
				for (int i = 0; i < weights.length; i++) {
					weights[i] = Integer.parseInt(_weights[i]);
				}
				sashForm.setWeights(weights);
			}
		} catch (Throwable e) {
			//None of this stuff is critical so shouldn't stop opening dialog if it fails!
			QuickSearchActivator.log(e);
		}
	}

	private class ToggleKeepOpenAction extends Action {
		public ToggleKeepOpenAction(IDialogSettings settings) {
			super(
					Messages.QuickSearchDialog_keepOpen_toggle,
					IAction.AS_CHECK_BOX
			);
			if (settings.get(KEEP_OPEN)==null) {
				setChecked(KEEP_OPEN_DEFAULT);
			} else{
				setChecked(settings.getBoolean(KEEP_OPEN));
			}
		}

		@Override
		public void run() {
			//setChecked(!isChecked());
		}

	}


	private class ToggleCaseSensitiveAction extends Action {

		public ToggleCaseSensitiveAction(IDialogSettings settings) {
			super(
					Messages.QuickSearchDialog_caseSensitive_toggle,
					IAction.AS_CHECK_BOX
			);
			if (settings.get(CASE_SENSITIVE)==null) {
				setChecked(CASE_SENSITIVE_DEFAULT);
			} else{
				setChecked(settings.getBoolean(CASE_SENSITIVE));
			}
		}

		@Override
		public void run() {
			//setChecked(!isChecked());
			refreshHeaderLabel();
			applyFilter(false);
		}
	}


	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jface.window.Window#close()
	 */
	@Override
	public boolean close() {
		this.progressJob.cancel();
		this.progressJob = null;
//		this.refreshProgressMessageJob.cancel();
		if (showViewHandler != null) {
			IHandlerService service = PlatformUI
					.getWorkbench().getService(IHandlerService.class);
			service.deactivateHandler(showViewHandler);
			showViewHandler.getHandler().dispose();
			showViewHandler = null;
		}
		if (menuManager != null)
			menuManager.dispose();
		if (contextMenuManager != null)
			contextMenuManager.dispose();
		storeDialog(getDialogSettings());
		if (searcher!=null) {
			searcher.cancel();
		}
		return super.close();
	}

	/**
	 * Stores dialog settings.
	 *
	 * @param settings
	 *           settings used to store dialog
	 */
	protected void storeDialog(IDialogSettings settings) {
		String currentSearch = pattern.getText();
		settings.put(DIALOG_LAST_QUERY, currentSearch);
		settings.put(DIALOG_PATH_FILTER, searchIn.getText());
		if (toggleCaseSensitiveAction!=null) {
			settings.put(CASE_SENSITIVE, toggleCaseSensitiveAction.isChecked());
		}
		if (toggleKeepOpenAction!=null) {
			settings.put(KEEP_OPEN, toggleKeepOpenAction.isChecked());
		}
		Table table = list.getTable();
		if (table.getColumnCount()>0) {
			String[] columnWidths = new String[table.getColumnCount()];
			for (int i = 0; i < columnWidths.length; i++) {
				columnWidths[i] = Integer.toString(table.getColumn(i).getWidth());
			}
			settings.put(DIALOG_COLUMNS, columnWidths);
		}
		if (sashForm.getWeights()!=null) {
			int[] w = sashForm.getWeights();
			String[] ws = new String[w.length];
			for (int i = 0; i < ws.length; i++) {
				ws[i] = Integer.toString(w[i]);
			}
			settings.put(DIALOG_SASH_WEIGHTS, ws);
		}
	}

	/**
	 * Create a new header which is labelled by headerLabel.
	 *
	 * @param parent
	 * @return Label the label of the header
	 */
	private Label createHeader(Composite parent) {
		Composite header = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		header.setLayout(layout);

		headerLabel = new Label(header, SWT.NONE);
		headerLabel.addTraverseListener(e -> {
			if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
				e.detail = SWT.TRAVERSE_NONE;
				pattern.setFocus();
			}
		});

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		headerLabel.setLayoutData(gd);

		createViewMenu(header);
		header.setLayoutData(gd);

		refreshHeaderLabel();
		return headerLabel;
	}

	private void refreshHeaderLabel() {
		String msg = toggleCaseSensitiveAction.isChecked() ? Messages.QuickSearchDialog_caseSensitive_label : Messages.QuickSearchDialog_caseInsensitive_label;
		headerLabel.setText(msg);
	}

	/**
	 * Create the labels for the list and the progress. Return the list label.
	 *
	 * @param parent
	 * @return Label
	 */
	private Label createLabels(Composite parent) {
		Composite labels = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		labels.setLayout(layout);

		Label listLabel = new Label(labels, SWT.NONE);
		listLabel
				.setText(WorkbenchMessages.FilteredItemsSelectionDialog_listLabel);

		listLabel.addTraverseListener(e -> {
			if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
				e.detail = SWT.TRAVERSE_NONE;
				list.getTable().setFocus();
			}
		});

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		listLabel.setLayoutData(gd);

		progressLabel = new Label(labels, SWT.RIGHT);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		progressLabel.setLayoutData(gd);
		createButton(labels, REFRESH_BUTTON_ID, Messages.QuickSearchDialog_Refresh, false);

		labels.setLayoutData(gd);
		return listLabel;
	}

	private void createViewMenu(Composite parent) {
		toolBar = new ToolBar(parent, SWT.FLAT);
		toolItem = new ToolItem(toolBar, SWT.PUSH, 0);

		GridData data = new GridData();
		data.horizontalAlignment = GridData.END;
		toolBar.setLayoutData(data);

		toolBar.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				showViewMenu();
			}
		});

		toolItem.setImage(WorkbenchImages
				.getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU));
		toolItem
				.setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu);
		toolItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				showViewMenu();
			}
		});

		menuManager = new MenuManager();

		fillViewMenu(menuManager);

		IHandlerService service = PlatformUI.getWorkbench()
				.getService(IHandlerService.class);
		IHandler handler = new AbstractHandler() {
			@Override
			public Object execute(ExecutionEvent event) {
				showViewMenu();
				return null;
			}
		};
		showViewHandler = service.activateHandler(
				IWorkbenchCommandConstants.WINDOW_SHOW_VIEW_MENU, handler,
				new ActiveShellExpression(getShell()));
	}

	/**
	 * Fills the menu of the dialog.
	 *
	 * @param menuManager
	 *           the menu manager
	 */
	protected void fillViewMenu(IMenuManager menuManager) {
		IDialogSettings settings = getDialogSettings();
		toggleCaseSensitiveAction = new ToggleCaseSensitiveAction(settings);
		menuManager.add(toggleCaseSensitiveAction);
		toggleKeepOpenAction = new ToggleKeepOpenAction(settings);
		menuManager.add(toggleKeepOpenAction);
	}

	private void showViewMenu() {
		Menu menu = menuManager.createContextMenu(getShell());
		Rectangle bounds = toolItem.getBounds();
		Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
		topLeft = toolBar.toDisplay(topLeft);
		menu.setLocation(topLeft.x, topLeft.y);
		menu.setVisible(true);
	}

    /**
     * Hook that allows to add actions to the context menu.
	 * <p>
	 * Subclasses may extend in order to add other actions.</p>
     *
     * @param menuManager the context menu manager
     * @since 3.5
     */
	protected void fillContextMenu(IMenuManager menuManager) {
	}

	private void createPopupMenu() {

		contextMenuManager = new MenuManager();
		contextMenuManager.setRemoveAllWhenShown(true);
		contextMenuManager.addMenuListener(this::fillContextMenu);

		final Table table = list.getTable();
		Menu menu= contextMenuManager.createContextMenu(table);
		table.setMenu(menu);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite dialogArea = (Composite) super.createDialogArea(parent);

		dialogArea.addDisposeListener(e -> QuickSearchDialog.this.dispose());

		Composite content = createNestedComposite(dialogArea, 1, false);
		GridData gd = new GridData(GridData.FILL_BOTH);
		content.setLayoutData(gd);

		final Label headerLabel = createHeader(content);

		Composite inputRow = createNestedComposite(content, 10, true);
		GridDataFactory.fillDefaults().grab(true, false).applyTo(inputRow);
		pattern = new Text(inputRow, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
		pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() {
			@Override
			public void getName(AccessibleEvent e) {
				e.result = LegacyActionTools.removeMnemonics(headerLabel
						.getText());
			}
		});
		GridDataFactory.fillDefaults().span(6,1).grab(true, false).applyTo(pattern);

		Composite searchInComposite = createNestedComposite(inputRow, 2, false);
		GridDataFactory.fillDefaults().span(4,1).grab(true, false).applyTo(searchInComposite);
		Label searchInLabel = new Label(searchInComposite, SWT.NONE);
		searchInLabel.setText(Messages.QuickSearchDialog_In);
		GridDataFactory.swtDefaults().indent(5, 0).applyTo(searchInLabel);
		searchIn = new Text(searchInComposite, SWT.SINGLE | SWT.BORDER | SWT.ICON_CANCEL);
		searchIn.setToolTipText(Messages.QuickSearchDialog_InTooltip);
		GridDataFactory.fillDefaults().grab(true, false).indent(5, 0).applyTo(searchIn);

		final Label listLabel = createLabels(content);

		sashForm = new SashForm(content, SWT.VERTICAL);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(sashForm);

		list = new TableViewer(sashForm, (multi ? SWT.MULTI : SWT.SINGLE) |
				SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL);
//		ColumnViewerToolTipSupport.enableFor(list, ToolTip.NO_RECREATE);

		list.getTable().setHeaderVisible(true);
		list.getTable().setLinesVisible(true);
		list.getTable().getAccessible().addAccessibleListener(
				new AccessibleAdapter() {
					@Override
					public void getName(AccessibleEvent e) {
						if (e.childID == ACC.CHILDID_SELF) {
							e.result = LegacyActionTools
									.removeMnemonics(listLabel.getText());
						}
					}
				});
		list.setContentProvider(contentProvider);
//		new ScrollListener(list.getTable().getVerticalBar());
//		new SelectionChangedListener(list);

		TableViewerColumn col = new TableViewerColumn(list, SWT.RIGHT);
		col.setLabelProvider(LINE_NUMBER_LABEL_PROVIDER);
		col.getColumn().setText(Messages.QuickSearchDialog_line);
		col.getColumn().setWidth(40);
		col = new TableViewerColumn(list, SWT.LEFT);
		col.getColumn().setText(Messages.QuickSearchDialog_text);
		col.setLabelProvider(LINE_TEXT_LABEL_PROVIDER);
		col.getColumn().setWidth(400);
		col = new TableViewerColumn(list, SWT.LEFT);
		col.getColumn().setText(Messages.QuickSearchDialog_path);
		col.setLabelProvider(LINE_FILE_LABEL_PROVIDER);
		col.getColumn().setWidth(150);

		new TableResizeHelper(list).enableResizing();

		//list.setLabelProvider(getItemsListLabelProvider());
		list.setInput(new Object[0]);
		list.setItemCount(contentProvider.getNumberOfElements());
		gd = new GridData(GridData.FILL_BOTH);
		applyDialogFont(list.getTable());
		gd.heightHint= list.getTable().getItemHeight() * 15;
		list.getTable().setLayoutData(gd);

		createPopupMenu();

		pattern.addModifyListener(e -> {
			applyFilter(false);
		});

		searchIn.addModifyListener(e -> {
			applyPathMatcher();
		});

		pattern.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.ARROW_DOWN) {
					if (list.getTable().getItemCount() > 0) {
						list.getTable().setFocus();
						list.getTable().select(0);
						//programatic selection may not fire selection events so...
						refreshDetails();
					}
				}
			}
		});

		list.addSelectionChangedListener(event -> {
			StructuredSelection selection = (StructuredSelection) event
					.getSelection();
			handleSelected(selection);
		});

		list.addDoubleClickListener(event -> handleDoubleClick());

		list.getTable().addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {

				if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) == 0
						&& (e.stateMask & SWT.CTRL) == 0) {
					StructuredSelection selection = (StructuredSelection) list
							.getSelection();

					if (selection.size() == 1) {
						Object element = selection.getFirstElement();
						if (element.equals(list.getElementAt(0))) {
							pattern.setFocus();
						}
						list.getTable().notifyListeners(SWT.Selection,
								new Event());

					}
				}

				if (e.keyCode == SWT.ARROW_DOWN
						&& (e.stateMask & SWT.SHIFT) != 0
						&& (e.stateMask & SWT.CTRL) != 0) {

					list.getTable().notifyListeners(SWT.Selection, new Event());
				}

			}
		});

		createDetailsArea(sashForm);
		sashForm.setWeights(new int[] {5,2});

		applyDialogFont(content);

		restoreDialog(getDialogSettings());

		if (initialPatternText != null) {
			pattern.setText(initialPatternText);
		}

		switch (selectionMode) {
		case CARET_BEGINNING:
			pattern.setSelection(0, 0);
			break;
		case FULL_SELECTION:
			pattern.selectAll();
			break;
		}

		// apply filter even if pattern is empty (display history)
		applyFilter(false);

		return dialogArea;
	}

	private Composite createNestedComposite(Composite parent, int numRows, boolean equalRows) {
		Composite nested = new Composite(parent, SWT.NONE);
		{
			GridLayout layout = new GridLayout(numRows, equalRows);
			layout.marginWidth = 0;
			layout.marginHeight = 0;
			layout.marginLeft = 0;
			layout.marginRight = 0;
			layout.horizontalSpacing = 0;
			nested.setLayout(layout);
		}
		GridDataFactory.fillDefaults().grab(true, false).applyTo(nested);
		return nested;
	}

	protected void dispose() {
		if (blankImage!=null) {
			blankImage.dispose();
			blankImage = null;
		}
	}

	private void createDetailsArea(Composite parent) {
		details = new StyledText(parent, SWT.MULTI+SWT.READ_ONLY+SWT.BORDER+SWT.H_SCROLL+SWT.V_SCROLL);
		details.setFont(JFaceResources.getFont(TEXT_FONT));

		list.addSelectionChangedListener(event -> refreshDetails());
		details.addControlListener(new ControlAdapter() {
			@Override
			public void controlResized(ControlEvent e) {
				refreshDetails();
			}
		});
	}


	// Dumber version just using the a 'raw' StyledText widget.
	private void refreshDetails() {
		if (details!=null && list!=null && !list.getTable().isDisposed()) {
			if (documents==null) {
				documents = new DocumentFetcher();
			}
			IStructuredSelection sel = (IStructuredSelection) list.getSelection();
			if (sel==null || sel.isEmpty()) {
				details.setText(EMPTY_STRING);
			} else {
				//Not empty selection
				final int context = 100; // number of lines before and after match to include in preview
				int numLines = computeLines();
				if (numLines > 0) {
					LineItem item = (LineItem) sel.getFirstElement();
					IDocument document = documents.getDocument(item.getFile());
					if (document!=null) {
						try {
							int line = item.getLineNumber()-1; //in document lines are 0 based. In search 1 based.
							int contextStartLine = Math.max(line-(numLines-1)/2 - context, 0);
							int start = document.getLineOffset(contextStartLine);
							int end = document.getLength();
							try {
								IRegion lineInfo = document.getLineInformation(line + numLines/2 + context);
								end = lineInfo.getOffset() + lineInfo.getLength();
							} catch (BadLocationException e) {
								//Presumably line number is past the end of document.
								//ignore.
							}

							StyledString styledString = highlightMatches(document.get(start, end-start));
							details.setText(styledString.getString());
							details.setStyleRanges(styledString.getStyleRanges());
							details.setTopIndex(Math.max(line - contextStartLine - numLines/2, 0));
							return;
						} catch (BadLocationException e) {
						}
					}
				}
			}
			//empty selection or some error:
			details.setText(EMPTY_STRING);
		}
	}

	/**
	 * Computes how many lines of text can be displayed in the details section.
	 */
	private int computeLines() {
		if (details!=null && !details.isDisposed()) {
			int lineHeight = details.getLineHeight();
			int areaHeight = details.getClientArea().height;
			return (areaHeight + lineHeight - 1) / lineHeight;
		}
		return 0;
	}

	/**
	 * Helper function to highlight all the matches for the current query in a given piece
	 * of text.
	 *
	 * @return StyledString instance.
	 */
	private StyledString highlightMatches(String visibleText) {
		StyledString styledText = new StyledString(visibleText);
		List<TextRange> matches = getQuery().findAll(visibleText);
		for (TextRange m : matches) {
			styledText.setStyle(m.getOffset(), m.getLength(), HIGHLIGHT_STYLE);
		}
		return styledText;
	}

// Version using sourceviewer
//	private void refreshDetails() {
//		if (details!=null && list!=null && !list.getTable().isDisposed()) {
//			if (documents==null) {
//				documents = new DocumentFetcher();
//			}
//			IStructuredSelection sel = (IStructuredSelection) list.getSelection();
//			if (sel!=null && !sel.isEmpty()) {
//				//Not empty selection
//				LineItem item = (LineItem) sel.getFirstElement();
//				IDocument document = documents.getDocument(item.getFile());
//				try {
//					int line = item.getLineNumber()-1; //in document lines are 0 based. In search 1 based.
//					int start = document.getLineOffset(Math.max(line-2, 0));
//					int end = document.getLength();
//					try {
//						end = document.getLineOffset(line+3);
//					} catch (BadLocationException e) {
//						//Presumably line number is past the end of document.
//						//ignore.
//					}
//					details.setDocument(document, start, end-start);
//
//					String visibleText = document.get(start, end-start);
//					List<TextRange> matches = getQuery().findAll(visibleText);
//					Region visibleRegion = new Region(start, end-start);
//					TextPresentation presentation = new TextPresentation(visibleRegion, 20);
//					presentation.setDefaultStyleRange(new StyleRange(0, document.getLength(), null, null));
//					for (TextRange m : matches) {
//						presentation.addStyleRange(new StyleRange(m.start+start, m.len, null, YELLOW));
//					}
//					details.changeTextPresentation(presentation, true);
//
//					return;
//				} catch (BadLocationException e) {
//				}
//			}
//			details.setDocument(null);
//		}
//	}

	/**
	 * Handle selection in the items list by updating labels of selected and
	 * unselected items and refresh the details field using the selection.
	 *
	 * @param selection
	 *           the new selection
	 */
	protected void handleSelected(StructuredSelection selection) {
		IStatus status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
				IStatus.OK, EMPTY_STRING, null);

		updateStatus(status);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings()
	 */
	@Override
	protected IDialogSettings getDialogBoundsSettings() {
		IDialogSettings settings = getDialogSettings();
		IDialogSettings section = settings.getSection(DIALOG_BOUNDS_SETTINGS);
		if (section == null) {
			section = settings.addNewSection(DIALOG_BOUNDS_SETTINGS);
			section.put(DIALOG_HEIGHT, 500);
			section.put(DIALOG_WIDTH, 600);
		}
		return section;
	}

	/**
	 * Returns the dialog settings. Returned object can't be null.
	 *
	 * @return return dialog settings for this dialog
	 */
	protected IDialogSettings getDialogSettings() {
		IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
				.getDialogSettings().getSection(DIALOG_SETTINGS);

		if (settings == null) {
			settings = IDEWorkbenchPlugin.getDefault().getDialogSettings()
					.addNewSection(DIALOG_SETTINGS);
		}

		return settings;
	}

	/**
	 * Has to be called in UI thread.
	 */
	public void refreshWidgets() {
		if (list != null && !list.getTable().isDisposed()) {
			int itemCount = contentProvider.getNumberOfElements();
			list.setItemCount(itemCount);
			list.refresh(true, false);
			Button openButton = getButton(OPEN_BUTTON_ID);
			if (openButton!=null && !openButton.isDisposed()) {
				//Even if no element is selected. The dialog should be have as if the first
				//element in the list is selected. So the button is enabled if any
				//element is available in the list.
				openButton.setEnabled(itemCount>0);
			}

		}
	}

	/**
	 * Schedule refresh job.
	 */
	public void scheduleRefresh() {
		refreshJob.schedule();
//		refreshCacheJob.cancelAll();
//		refreshCacheJob.schedule();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
	 */
	@Override
	protected void computeResult() {
		List objectsToReturn = ((StructuredSelection) list.getSelection())
				.toList();
		if (objectsToReturn.isEmpty()) {
			//Pretend that the first element is selected.
			Object first = list.getElementAt(0);
			if (first!=null) {
				objectsToReturn = Arrays.asList(first);
			}
		}
		setResult(objectsToReturn);
	}



	/**
	 * Handles double-click of items, but *also* by pressing the 'enter' key.
	 */
	protected void handleDoubleClick() {
		okPressed();
	}

	protected void refreshButtonPressed() {
		applyFilter(true);
	}


	@Override
	protected void okPressed() {
		computeResult();
		openSelection();
		if (!toggleKeepOpenAction.isChecked()) {
			setReturnCode(OK);
			close();
		}
	}

	@Override
	protected void buttonPressed(int buttonId) {
		if (buttonId == REFRESH_BUTTON_ID) {
			refreshButtonPressed();
		} else {
			super.buttonPressed(buttonId);
		}
	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, OPEN_BUTTON_ID, Messages.QuickSearchDialog_Open, true);
		refreshWidgets();
	}

	/**
	 * Sets the initial pattern used by the filter. This text is copied into the
	 * selection input on the dialog. A full selection is used in the pattern
	 * input field.
	 *
	 * @param text
	 *           initial pattern for the filter
	 * @see QuickSearchDialog#FULL_SELECTION
	 */
	public void setInitialPattern(String text) {
		setInitialPattern(text, FULL_SELECTION);
	}

	/**
	 * Sets the initial pattern used by the filter. This text is copied into the
	 * selection input on the dialog. The <code>selectionMode</code> is used
	 * to choose selection type for the input field.
	 *
	 * @param text
	 *           initial pattern for the filter
	 * @param selectionMode
	 *           one of: {@link QuickSearchDialog#NONE},
	 *           {@link QuickSearchDialog#CARET_BEGINNING},
	 *           {@link QuickSearchDialog#FULL_SELECTION}
	 */
	public void setInitialPattern(String text, int selectionMode) {
		this.initialPatternText = text;
		this.selectionMode = selectionMode;
	}

	/**
	 * Gets initial pattern.
	 *
	 * @return initial pattern, or <code>null</code> if initial pattern is not
	 *        set
	 */
	protected String getInitialPattern() {
		return this.initialPatternText;
	}

	/**
	 * Returns the current selection.
	 *
	 * @return the current selection
	 */
	protected StructuredSelection getSelectedItems() {

		StructuredSelection selection = (StructuredSelection) list
				.getSelection();

		List selectedItems = selection.toList();

		return new StructuredSelection(selectedItems);
	}

	/**
	 * Validates the item. When items on the items list are selected or
	 * deselected, it validates each item in the selection and the dialog status
	 * depends on all validations.
	 *
	 * @param item
	 *           an item to be checked
	 * @return status of the dialog to be set
	 */
	protected IStatus validateItem(Object item) {
		return Status.OK_STATUS;
	}

	/**
	 * Creates an instance of a filter.
	 *
	 * @return a filter for items on the items list. Can be <code>null</code>,
	 *        no filtering will be applied then, causing no item to be shown in
	 *        the list.
	 */
	protected QuickTextQuery createFilter() {
		return new QuickTextQuery(pattern.getText(), toggleCaseSensitiveAction.isChecked());
	}

	/**
	 * Applies the filter created by <code>createFilter()</code> method to the
	 * items list. When new filter is different than previous one it will cause
	 * refiltering.
	 * <p>
	 * The 'force' parameter forces a full refresh of the search results / filter even
	 * when the filter is unchanged, or when a incremenal filtering optimisation could be
	 * applied based on query structure. (The use case for this, is to trigger forced refresh
	 * because the underlying resources may have changed).
	 */
	protected void applyFilter(boolean force) {
		QuickTextQuery newFilter = createFilter();
		if (this.searcher==null) {
			if (!newFilter.isTrivial()) {
				//Create the QuickTextSearcher with the inital query.
				this.searcher = new QuickTextSearcher(newFilter, context.createPriorityFun(), MAX_LINE_LEN, new QuickTextSearchRequestor() {
					@Override
					public void add(LineItem match) {
						contentProvider.add(match);
						contentProvider.refresh();
					}
					@Override
					public void clear() {
						contentProvider.reset();
						contentProvider.refresh();
					}
					@Override
					public void revoke(LineItem match) {
						contentProvider.remove(match);
						contentProvider.refresh();
					}
					@Override
					public void update(LineItem match) {
						contentProvider.refresh();
					}
				});
				applyPathMatcher();
				refreshWidgets();
			}
//			this.list.setInput(input)
		} else {
			//The QuickTextSearcher is already active update the query
			this.searcher.setQuery(newFilter, force);
		}
		if (progressJob!=null) {
			progressJob.schedule();
		}
	}

	private void applyPathMatcher() {
		if (this.searcher!=null) {
			this.searcher.setPathMatcher(ResourceMatchers.commaSeparatedPaths(searchIn.getText()));
		}
	}



	/**
	 * Returns name for then given object.
	 *
	 * @param item
	 *           an object from the content provider. Subclasses should pay
	 *           attention to the passed argument. They should either only pass
	 *           objects of a known type (one used in content provider) or make
	 *           sure that passed parameter is the expected one (by type
	 *           checking like <code>instanceof</code> inside the method).
	 * @return name of the given item
	 */
	public String getElementName(Object item) {
		return Objects.toString(item);
	}

	/**
	 * Collects filtered elements. Contains one synchronized, sorted set for
	 * collecting filtered elements.
	 * Implementation of <code>ItemsFilter</code> is used to filter elements.
	 * The key function of filter used in to filtering is
	 * <code>matchElement(Object item)</code>.
	 * <p>
	 * The <code>ContentProvider</code> class also provides item filtering
	 * methods. The filtering has been moved from the standard TableView
	 * <code>getFilteredItems()</code> method to content provider, because
	 * <code>ILazyContentProvider</code> and virtual tables are used. This
	 * class is responsible for adding a separator below history items and
	 * marking each items as duplicate if its name repeats more than once on the
	 * filtered list.
	 */
	private class ContentProvider implements IStructuredContentProvider, ILazyContentProvider {

		private List items;

		/**
		 * Creates new instance of <code>ContentProvider</code>.
		 */
		public ContentProvider() {
			this.items = Collections.synchronizedList(new ArrayList(2048));
//			this.duplicates = Collections.synchronizedSet(new HashSet(256));
//			this.lastSortedItems = Collections.synchronizedList(new ArrayList(
//					2048));
		}

		public void remove(LineItem match) {
			this.items.remove(match);
		}

		/**
		 * Removes all content items and resets progress message.
		 */
		public void reset() {
			this.items.clear();
		}

		/**
		 * Adds filtered item.
		 *
		 * @param match
		 */
		public void add(LineItem match) {
			this.items.add(match);
		}

		/**
		 * Refresh dialog.
		 */
		public void refresh() {
			scheduleRefresh();
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
		 */
		@Override
		public Object[] getElements(Object inputElement) {
			return items.toArray();
		}

		public int getNumberOfElements() {
			return items.size();
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
		 */
		@Override
		public void dispose() {
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
		 *     java.lang.Object, java.lang.Object)
		 */
		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jface.viewers.ILazyContentProvider#updateElement(int)
		 */
		@Override
		public void updateElement(int index) {

			QuickSearchDialog.this.list.replace((items
					.size() > index) ? items.get(index) : null,
					index);

		}

	}

	/**
	 * Get the control where the search pattern is entered. Any filtering should
	 * be done using an {@link ItemsFilter}. This control should only be
	 * accessed for listeners that wish to handle events that do not affect
	 * filtering such as custom traversal.
	 *
	 * @return Control or <code>null</code> if the pattern control has not
	 *        been created.
	 */
	public Control getPatternControl() {
		return pattern;
	}

	public QuickTextQuery getQuery() {
		return searcher.getQuery();
	}

}
