/*******************************************************************************
 * 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 v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.dltk.ui.dialogs;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.core.Flags;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.index2.search.ModelAccess;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.NopTypeNameRequestor;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.TypeNameMatch;
import org.eclipse.dltk.core.search.TypeNameMatchRequestor;
import org.eclipse.dltk.internal.core.search.DLTKSearchTypeNameMatch;
import org.eclipse.dltk.internal.corext.util.Messages;
import org.eclipse.dltk.internal.corext.util.OpenTypeHistory;
import org.eclipse.dltk.internal.corext.util.Strings;
import org.eclipse.dltk.internal.corext.util.TypeFilter;
import org.eclipse.dltk.internal.corext.util.TypeInfoRequestorAdapter;
import org.eclipse.dltk.internal.ui.DLTKUIMessages;
import org.eclipse.dltk.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.dltk.internal.ui.search.DLTKSearchScopeFactory;
import org.eclipse.dltk.internal.ui.util.TypeNameMatchLabelProvider;
import org.eclipse.dltk.internal.ui.workingsets.WorkingSetFilterActionGroup;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.IInterpreterInstallType;
import org.eclipse.dltk.launching.LibraryLocation;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.ui.DLTKUILanguageManager;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.IDLTKUILanguageToolkit;
import org.eclipse.dltk.ui.ScriptElementImageProvider;
import org.eclipse.dltk.ui.ScriptElementLabels;
import org.eclipse.dltk.ui.util.ExceptionHandler;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.dialogs.SearchPattern;

/**
 * Shows a list of Java types to the user with a text entry field for a string
 * pattern used to filter the list of types.
 *
 * @since 3.3
 */
public class FilteredTypesSelectionDialog extends FilteredItemsSelectionDialog implements ITypeSelectionComponent {

	private static final String DIALOG_SETTINGS = "org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog"; //$NON-NLS-1$

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

	private WorkingSetFilterActionGroup fFilterActionGroup;

	private final TypeItemLabelProvider fTypeInfoLabelProvider;

	private String fTitle;

	private IDLTKSearchScope fSearchScope;

	private boolean fAllowScopeSwitching;

	private final int fElementKinds;

	private final ITypeInfoFilterExtension fFilterExtension;

	private final TypeSelectionExtension fExtension;

	private ISelectionStatusValidator fValidator;

	private final TypeInfoUtil fTypeInfoUtil;

	private static boolean fgFirstTime = true;

	private final TypeItemsComparator fTypeItemsComparator;

	private int fTypeFilterVersion = 0;

	private IDLTKLanguageToolkit fToolkit;

	/**
	 * Creates new FilteredTypesSelectionDialog instance
	 *
	 * @param parent       shell to parent the dialog on
	 * @param multi        <code>true</code> if multiple selection is allowed
	 * @param context      context used to execute long-running operations
	 *                     associated with this dialog
	 * @param scope        scope used when searching for types
	 * @param elementKinds flags defining nature of searched elements; the only
	 *                     valid values are: <code>IJavaSearchConstants.TYPE</code>
	 *                     <code>IJavaSearchConstants.ANNOTATION_TYPE</code>
	 *                     <code>IJavaSearchConstants.INTERFACE</code>
	 *                     <code>IJavaSearchConstants.ENUM</code>
	 *                     <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code>
	 *                     <code>IJavaSearchConstants.CLASS_AND_ENUM</code>. Please
	 *                     note that the bitwise OR combination of the elementary
	 *                     constants is not supported.
	 */
	public FilteredTypesSelectionDialog(Shell parent, boolean multi, IRunnableContext context, IDLTKSearchScope scope,
			int elementKinds, IDLTKLanguageToolkit toolkit) {
		this(parent, multi, context, scope, elementKinds, null, toolkit);
	}

	/**
	 * Creates new FilteredTypesSelectionDialog instance.
	 *
	 * @param shell        shell to parent the dialog on
	 * @param multi        <code>true</code> if multiple selection is allowed
	 * @param context      context used to execute long-running operations
	 *                     associated with this dialog
	 * @param scope        scope used when searching for types. If the scope is
	 *                     <code>null</code>, then workspace is scope is used as
	 *                     default, and the user can choose a working set as scope.
	 * @param elementKinds flags defining nature of searched elements; the only
	 *                     valid values are: <code>IJavaSearchConstants.TYPE</code>
	 *                     <code>IJavaSearchConstants.ANNOTATION_TYPE</code>
	 *                     <code>IJavaSearchConstants.INTERFACE</code>
	 *                     <code>IJavaSearchConstants.ENUM</code>
	 *                     <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code>
	 *                     <code>IJavaSearchConstants.CLASS_AND_ENUM</code>. Please
	 *                     note that the bitwise OR combination of the elementary
	 *                     constants is not supported.
	 * @param extension    an extension of the standard type selection dialog; See
	 *                     {@link TypeSelectionExtension}
	 */
	public FilteredTypesSelectionDialog(Shell shell, boolean multi, IRunnableContext context, IDLTKSearchScope scope,
			int elementKinds, TypeSelectionExtension extension, IDLTKLanguageToolkit toolkit) {
		super(shell, multi);

		this.fToolkit = toolkit;

		setSelectionHistory(new TypeSelectionHistory());

		if (scope == null) {
			fAllowScopeSwitching = true;
			scope = SearchEngine.createWorkspaceScope(toolkit);
		}
		// PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
		// IJavaHelpContextIds.TYPE_SELECTION_DIALOG2);

		fElementKinds = elementKinds;
		fExtension = extension;
		fFilterExtension = (extension == null) ? null : extension.getFilterExtension();
		fSearchScope = scope;

		if (extension != null) {
			fValidator = extension.getSelectionValidator();
		}

		fTypeInfoUtil = new TypeInfoUtil(extension != null ? extension.getImageProvider() : null);

		fTypeInfoLabelProvider = new TypeItemLabelProvider();

		setListLabelProvider(fTypeInfoLabelProvider);
		setListSelectionLabelDecorator(fTypeInfoLabelProvider);
		setDetailsLabelProvider(new TypeItemDetailsLabelProvider(fTypeInfoUtil));

		fTypeItemsComparator = new TypeItemsComparator();
	}

	@Override
	public void setTitle(String title) {
		super.setTitle(title);
		fTitle = title;
	}

	/**
	 * Adds or replaces subtitle of the dialog
	 *
	 * @param text the new subtitle for this dialog
	 */
	private void setSubtitle(String text) {
		if (text == null || text.length() == 0) {
			getShell().setText(fTitle);
		} else {
			getShell().setText(Messages.format(DLTKUIMessages.FilteredTypeSelectionDialog_titleFormat, fTitle, text));
		}
	}

	@Override
	protected IDialogSettings getDialogSettings() {
		IDialogSettings settings = DLTKUIPlugin.getDefault().getDialogSettings().getSection(DIALOG_SETTINGS);

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

		return settings;
	}

	@Override
	protected void storeDialog(IDialogSettings settings) {
		super.storeDialog(settings);

		if (fFilterActionGroup != null) {
			XMLMemento memento = XMLMemento.createWriteRoot("workingSet"); //$NON-NLS-1$
			fFilterActionGroup.saveState(memento);
			fFilterActionGroup.dispose();
			StringWriter writer = new StringWriter();
			try {
				memento.save(writer);
				settings.put(WORKINGS_SET_SETTINGS, writer.getBuffer().toString());
			} catch (IOException e) {
				// don't do anything. Simply don't store the settings
				DLTKUIPlugin.log(e);
			}
		}
	}

	@Override
	protected void restoreDialog(IDialogSettings settings) {
		super.restoreDialog(settings);

		fTypeInfoLabelProvider.setContainerInfo(true);

		if (fAllowScopeSwitching) {
			String setting = settings.get(WORKINGS_SET_SETTINGS);
			if (setting != null) {
				try {
					IMemento memento = XMLMemento.createReadRoot(new StringReader(setting));
					fFilterActionGroup.restoreState(memento);
				} catch (WorkbenchException e) {
					// don't do anything. Simply don't restore the settings
					DLTKUIPlugin.log(e);
				}
			}
			IWorkingSet ws = fFilterActionGroup.getWorkingSet();
			if (ws == null || (ws.isAggregateWorkingSet() && ws.isEmpty())) {
				setSearchScope(SearchEngine.createWorkspaceScope(fToolkit));
				setSubtitle(null);
			} else {
				setSearchScope(DLTKSearchScopeFactory.getInstance().createSearchScope(ws, true, fToolkit));
				setSubtitle(ws.getLabel());
			}
		}

		// TypeNameMatch[] types = OpenTypeHistory.getInstance().getTypeInfos();
		//
		// for (int i = 0; i < types.length; i++) {
		// TypeNameMatch type = types[i];
		// accessedHistoryItem(type);
		// }
	}

	@Override
	protected void fillViewMenu(IMenuManager menuManager) {
		super.fillViewMenu(menuManager);

		if (fAllowScopeSwitching) {
			fFilterActionGroup = new WorkingSetFilterActionGroup(getShell(), DLTKUIPlugin.getActivePage(), event -> {
				IWorkingSet ws = (IWorkingSet) event.getNewValue();
				if (ws == null || (ws.isAggregateWorkingSet() && ws.isEmpty())) {
					setSearchScope(SearchEngine.createWorkspaceScope(fToolkit));
					setSubtitle(null);
				} else {
					setSearchScope(DLTKSearchScopeFactory.getInstance().createSearchScope(ws, true, fToolkit));
					setSubtitle(ws.getLabel());
				}

				applyFilter();
			});
			fFilterActionGroup.fillViewMenu(menuManager);
		}

		// menuManager.add(new Separator());
		// menuManager.add(new TypeFiltersPreferencesAction());
	}

	@Override
	protected Control createExtendedContentArea(Composite parent) {
		Control addition = null;

		if (fExtension != null) {

			addition = fExtension.createContentArea(parent);
			if (addition != null) {
				GridData gd = new GridData(GridData.FILL_HORIZONTAL);
				gd.horizontalSpan = 2;
				addition.setLayoutData(gd);

			}

			fExtension.initialize(this);
		}

		return addition;
	}

	@Override
	protected void setResult(List newResult) {

		List<IType> resultToReturn = new ArrayList<>();

		for (int i = 0; i < newResult.size(); i++) {
			if (newResult.get(i) instanceof TypeNameMatch) {
				IType type = ((TypeNameMatch) newResult.get(i)).getType();
				if (type.exists()) {
					// items are added to history in the
					// org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#computeResult()
					// method
					resultToReturn.add(type);
				} else {
					TypeNameMatch typeInfo = (TypeNameMatch) newResult.get(i);
					IProjectFragment root = typeInfo.getProjectFragment();
					IDLTKUILanguageToolkit uiToolkit = DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId());
					ScriptElementLabels labels = uiToolkit.getScriptElementLabels();
					String containerName = labels.getElementLabel(root, ScriptElementLabels.ALL_FULLY_QUALIFIED);
					String message = Messages.format(DLTKUIMessages.FilteredTypesSelectionDialog_dialogMessage,
							typeInfo.getFullyQualifiedName(), containerName);
					MessageDialog.openError(getShell(), fTitle, message);
					getSelectionHistory().remove(typeInfo);
				}
			}
		}

		super.setResult(resultToReturn);
	}

	@Override
	public void create() {
		super.create();
		Control patternControl = getPatternControl();
		if (patternControl instanceof Text) {
			TextFieldNavigationHandler.install((Text) patternControl);
		}
	}

	@Override
	public int open() {
		if (getInitialPattern() == null) {
			IWorkbenchWindow window = DLTKUIPlugin.getActiveWorkbenchWindow();
			if (window != null) {
				ISelection selection = window.getSelectionService().getSelection();
				if (selection instanceof ITextSelection) {
					String text = ((ITextSelection) selection).getText();
					if (text != null) {
						text = text.trim();
						if (text.length() > 0) {
							setInitialPattern(text, FULL_SELECTION);
						}
					}
				}
			}
		}
		return super.open();
	}

	/**
	 * Sets a new validator.
	 *
	 * @param validator the new validator
	 */
	public void setValidator(ISelectionStatusValidator validator) {
		fValidator = validator;
	}

	@Override
	protected ItemsFilter createFilter() {
		return new TypeItemsFilter(fSearchScope, fElementKinds, fFilterExtension);
	}

	@Override
	protected Control createContents(Composite parent) {
		Control contents = super.createContents(parent);
		// if (ColoredViewersManager.showColoredLabels()) {
		// if (contents instanceof Composite) {
		// Table listControl = findTableControl((Composite) contents);
		// if (listControl != null) {
		// installOwnerDraw(listControl);
		// }
		// }
		// }
		return contents;
	}

	@Override
	protected void fillContentProvider(AbstractContentProvider provider, ItemsFilter itemsFilter,
			IProgressMonitor progressMonitor) throws CoreException {
		TypeItemsFilter typeSearchFilter = (TypeItemsFilter) itemsFilter;
		TypeSearchRequestor requestor = new TypeSearchRequestor(provider, typeSearchFilter);
		String typePattern = itemsFilter.getPattern();

		progressMonitor.setTaskName(DLTKUIMessages.FilteredTypesSelectionDialog_searchJob_taskName);

		IType[] types = new ModelAccess().findTypes(typePattern,
				ModelAccess.convertSearchRule(itemsFilter.getMatchRule()), 0, Modifiers.AccNameSpace,
				typeSearchFilter.getSearchScope(), progressMonitor);
		if (types != null) {
			for (IType type : types) {
				requestor.acceptTypeNameMatch(new DLTKSearchTypeNameMatch(type, type.getFlags()));
			}
		} else {

			SearchEngine engine = new SearchEngine((WorkingCopyOwner) null);
			String packPattern = typeSearchFilter.getPackagePattern();

			/*
			 * Setting the filter into match everything mode avoids filtering twice by the
			 * same pattern (the search engine only provides filtered matches). For the case
			 * when the pattern is a camel case pattern with a terminator, the filter is not
			 * set to match everything mode because jdt.core's SearchPattern does not
			 * support that case.
			 */
			int matchRule = typeSearchFilter.getMatchRule();
			if (matchRule == SearchPattern.RULE_CAMELCASE_MATCH) {
				// If the pattern is empty, the RULE_BLANK_MATCH will be chosen,
				// so
				// we don't have to check the pattern length
				char lastChar = typePattern.charAt(typePattern.length() - 1);

				if (lastChar == '<' || lastChar == ' ') {
					typePattern = typePattern.substring(0, typePattern.length() - 1);
				} else {
					typeSearchFilter.setMatchEverythingMode(true);
				}
			} else {
				typeSearchFilter.setMatchEverythingMode(true);
			}

			try {
				engine.searchAllTypeNames(packPattern == null ? null : packPattern.toCharArray(),
						typeSearchFilter.getPackageFlags(), typePattern.toCharArray(), matchRule,
						typeSearchFilter.getElementKind(), typeSearchFilter.getSearchScope(), requestor,
						IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, progressMonitor);
			} finally {
				typeSearchFilter.setMatchEverythingMode(false);
			}
		}
	}

	@Override
	protected Comparator getItemsComparator() {
		return fTypeItemsComparator;
	}

	@Override
	public String getElementName(Object item) {
		TypeNameMatch type = (TypeNameMatch) item;
		return fTypeInfoUtil.getText(type);
	}

	@Override
	protected IStatus validateItem(Object item) {

		if (item == null)
			return new Status(IStatus.ERROR, DLTKUIPlugin.getPluginId(), IStatus.ERROR, "", null); //$NON-NLS-1$

		if (fValidator != null) {
			IType type = ((TypeNameMatch) item).getType();
			if (!type.exists())
				return new Status(IStatus.ERROR, DLTKUIPlugin.getPluginId(), IStatus.ERROR,
						Messages.format(DLTKUIMessages.FilteredTypesSelectionDialog_error_type_doesnot_exist,
								((TypeNameMatch) item).getFullyQualifiedName()),
						null);
			Object[] elements = { type };
			return fValidator.validate(elements);
		}
		return new Status(IStatus.OK, DLTKUIPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
	}

	/**
	 * Sets search scope used when searching for types.
	 *
	 * @param scope the new scope
	 */
	private void setSearchScope(IDLTKSearchScope scope) {
		fSearchScope = scope;
	}

	/*
	 * We only have to ensure history consistency here since the search engine takes
	 * care of working copies.
	 */
	private static class ConsistencyRunnable implements IRunnableWithProgress {
		private IDLTKUILanguageToolkit tookit;

		ConsistencyRunnable(IDLTKLanguageToolkit toolkit) {
			this.tookit = DLTKUILanguageManager.getLanguageToolkit(toolkit.getNatureId());
		}

		@Override
		public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
			if (fgFirstTime) {
				// Join the initialize after load job.
				IJobManager manager = Job.getJobManager();
				manager.join(DLTKUIPlugin.PLUGIN_ID, monitor);
			}
			OpenTypeHistory history = OpenTypeHistory.getInstance(tookit);
			if (fgFirstTime || history.isEmpty()) {
				if (history.needConsistencyCheck()) {
					SubMonitor subMonitor = SubMonitor.convert(monitor,
							DLTKUIMessages.TypeSelectionDialog_progress_consistency, 100);
					refreshSearchIndices(subMonitor.split(90));
					history.checkConsistency(subMonitor.split(10));
				} else {
					refreshSearchIndices(monitor);
				}
				fgFirstTime = false;
			} else {
				history.checkConsistency(monitor);
			}
		}

		public static boolean needsExecution(IDLTKLanguageToolkit toolkit) {
			OpenTypeHistory history = OpenTypeHistory
					.getInstance(DLTKUILanguageManager.getLanguageToolkit(toolkit.getNatureId()));
			return fgFirstTime || history.isEmpty() || history.needConsistencyCheck();
		}

		private void refreshSearchIndices(IProgressMonitor monitor) throws InvocationTargetException {
			try {
				new SearchEngine().searchAllTypeNames(null, 0,
						// make sure we search a concrete name. This is faster
						// according to Kent
						"_______________".toCharArray(), //$NON-NLS-1$
						SearchPattern.RULE_EXACT_MATCH | SearchPattern.RULE_CASE_SENSITIVE, IDLTKSearchConstants.TYPE,
						SearchEngine.createWorkspaceScope(tookit.getCoreToolkit()), new NopTypeNameRequestor(),
						IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
			} catch (ModelException e) {
				throw new InvocationTargetException(e);
			}
		}
	}

	@Override
	public void reloadCache(boolean checkDuplicates, IProgressMonitor monitor) {
		IProgressMonitor remainingMonitor;
		SubMonitor subMonitor = SubMonitor.convert(monitor, DLTKUIMessages.TypeSelectionDialog_progress_consistency,
				10);
		if (ConsistencyRunnable.needsExecution(fToolkit)) {
			try {
				ConsistencyRunnable runnable = new ConsistencyRunnable(fToolkit);
				runnable.run(subMonitor.split(1));
			} catch (InvocationTargetException e) {
				ExceptionHandler.handle(e, DLTKUIMessages.TypeSelectionDialog_error3Title,
						DLTKUIMessages.TypeSelectionDialog_error3Message);
				close();
				return;
			} catch (InterruptedException e) {
				// cancelled by user
				close();
				return;
			}
			remainingMonitor = subMonitor.split(9);
		} else {
			remainingMonitor = subMonitor;
		}
		super.reloadCache(checkDuplicates, remainingMonitor);
	}

	@Override
	public void triggerSearch() {
		fTypeFilterVersion++;
		applyFilter();
	}

	/**
	 * A <code>LabelProvider</code> for (the table of) types.
	 */
	private class TypeItemLabelProvider extends LabelProvider implements ILabelDecorator {

		private boolean fContainerInfo;

		/**
		 * Construct a new <code>TypeItemLabelProvider</code>. F
		 */
		public TypeItemLabelProvider() {

		}

		public void setContainerInfo(boolean containerInfo) {
			fContainerInfo = containerInfo;
			fireLabelProviderChanged(new LabelProviderChangedEvent(this));
		}

		@Override
		public Image getImage(Object element) {
			if (!(element instanceof TypeNameMatch)) {
				return super.getImage(element);
			}

			TypeNameMatch type = (TypeNameMatch) element;

			ImageDescriptor iD = ScriptElementImageProvider.getTypeImageDescriptor(type.getModifiers(), false);

			return DLTKUIPlugin.getImageDescriptorRegistry().get(iD);
		}

		@Override
		public String getText(Object element) {
			if (!(element instanceof TypeNameMatch)) {
				return super.getText(element);
			}

			if (fContainerInfo && isDuplicateElement(element)) {
				return fTypeInfoUtil.getFullyQualifiedText((TypeNameMatch) element);
			}

			if (!fContainerInfo && isDuplicateElement(element)) {
				return fTypeInfoUtil.getQualifiedText((TypeNameMatch) element);
			}

			return fTypeInfoUtil.getText(element);
		}

		@Override
		public Image decorateImage(Image image, Object element) {
			return null;
		}

		@Override
		public String decorateText(String text, Object element) {
			if (!(element instanceof TypeNameMatch)) {
				return null;
			}

			if (fContainerInfo && isDuplicateElement(element)) {
				return fTypeInfoUtil.getFullyQualifiedText((TypeNameMatch) element);
			}

			return fTypeInfoUtil.getQualifiedText((TypeNameMatch) element);
		}

	}

	/**
	 * A <code>LabelProvider</code> for the label showing type details.
	 */
	private class TypeItemDetailsLabelProvider extends LabelProvider {

		private TypeNameMatchLabelProvider fLabelProvider;

		private final TypeInfoUtil fTypeInfoUtil;

		public TypeItemDetailsLabelProvider(TypeInfoUtil typeInfoUtil) {
			fTypeInfoUtil = typeInfoUtil;

			fLabelProvider = new TypeNameMatchLabelProvider(
					TypeNameMatchLabelProvider.SHOW_TYPE_ONLY + TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED,
					DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId()));
		}

		@Override
		public Image getImage(Object element) {
			if (element instanceof TypeNameMatch) {
				return fLabelProvider.getImage((element));
			}

			return super.getImage(element);
		}

		@Override
		public String getText(Object element) {
			if (element instanceof TypeNameMatch) {
				return fTypeInfoUtil.getQualificationText((TypeNameMatch) element);
			}

			return super.getText(element);
		}
	}

	private class TypeInfoUtil {

		private final ITypeInfoImageProvider fProviderExtension;

		private final TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter();

		private final Map<String, String> fLib2Name = new HashMap<>();

		private final String[] fInstallLocations;

		private final String[] fVMNames;

		public TypeInfoUtil(ITypeInfoImageProvider extension) {
			fProviderExtension = extension;
			List<String> locations = new ArrayList<>();
			List<String> labels = new ArrayList<>();
			IInterpreterInstallType[] installs = ScriptRuntime.getInterpreterInstallTypes(fToolkit.getNatureId());
			for (int i = 0; i < installs.length; i++) {
				processInterpreterInstallType(installs[i], locations, labels);
			}
			fInstallLocations = locations.toArray(new String[locations.size()]);
			fVMNames = labels.toArray(new String[labels.size()]);

		}

		private void processInterpreterInstallType(IInterpreterInstallType installType, List<String> locations,
				List<String> labels) {
			if (installType != null) {
				IInterpreterInstall[] installs = installType.getInterpreterInstalls();
				boolean isMac = Platform.OS_MACOSX.equals(Platform.getOS());
				final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$
				for (int i = 0; i < installs.length; i++) {
					String label = getFormattedLabel(installs[i].getName());
					LibraryLocation[] libLocations = installs[i].getLibraryLocations();
					if (libLocations != null) {
						processLibraryLocation(libLocations, label);
					} else {
						String filePath = installs[i].getInstallLocation().toOSString();
						if (filePath != null) {
							// on MacOS X install locations end in an additional
							// "/Home" segment; remove it
							if (isMac && filePath.endsWith(HOME_SUFFIX))
								filePath = filePath.substring(0, filePath.length() - HOME_SUFFIX.length() + 1);
							locations.add(filePath);
							labels.add(label);
						}
					}
				}
			}
		}

		private void processLibraryLocation(LibraryLocation[] libLocations, String label) {
			for (int l = 0; l < libLocations.length; l++) {
				LibraryLocation location = libLocations[l];
				fLib2Name.put(location.getLibraryPath().toOSString(), label);
			}
		}

		private String getFormattedLabel(String name) {
			return Messages.format(DLTKUIMessages.FilteredTypesSelectionDialog_library_name_format, name);
		}

		public String getText(Object element) {
			return ((TypeNameMatch) element).getSimpleTypeName();
		}

		public String getQualifiedText(TypeNameMatch type) {
			StringBuffer result = new StringBuffer();
			result.append(type.getSimpleTypeName());
			// String containerName = type.getTypeContainerName();
			// result.append(ScriptElementLabels.CONCAT_STRING);
			// if (containerName.length() > 0) {
			// result.append(containerName);
			// } else {
			// result.append("");
			// }
			return result.toString();
		}

		public String getFullyQualifiedText(TypeNameMatch type) {
			StringBuffer result = new StringBuffer();
			result.append(type.getSimpleTypeName());
			IType stype = type.getType();
			if (stype.getParent().getElementType() == IModelElement.TYPE) {
				result.append(ScriptElementLabels.CONCAT_STRING);
				IType parent = (IType) stype.getParent();
				result.append(parent.getTypeQualifiedName(".")); //$NON-NLS-1$
			}
			// String containerName = type.getTypeContainerName();
			// if (containerName.length() > 0) {
			// result.append(ScriptElementLabels.CONCAT_STRING);
			// result.append(containerName);
			// }
			// result.append(ScriptElementLabels.CONCAT_STRING);
			// result.append(getContainerName(type));
			return result.toString();
		}

		public String getQualificationText(TypeNameMatch type) {
			StringBuffer result = new StringBuffer();
			result.append(type.getType().getTypeQualifiedName(".")); //$NON-NLS-1$
			result.append(ScriptElementLabels.CONCAT_STRING);
			result.append(getContainerName(type));
			return result.toString();
		}

		private String getContainerName(TypeNameMatch type) {
			IProjectFragment root = type.getProjectFragment();
			if (root.isExternal()) {
				String name = root.getPath().toOSString();
				for (int i = 0; i < fInstallLocations.length; i++) {
					if (name.startsWith(fInstallLocations[i])) {
						return fVMNames[i];
					}
				}
				String lib = fLib2Name.get(name);
				if (lib != null)
					return lib;
			}
			StringBuffer buf = new StringBuffer();
			ScriptElementLabels labels = DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId())
					.getScriptElementLabels();
			labels.getProjectFragmentLabel(root, ScriptElementLabels.ROOT_QUALIFIED | ScriptElementLabels.ROOT_VARIABLE,
					buf);
			return buf.toString();
		}

	}

	/**
	 * Filters types using pattern, scope, element kind and filter extension.
	 */
	private class TypeItemsFilter extends ItemsFilter {

		private static final int TYPE_MODIFIERS = Flags.AccAnnotation | Flags.AccInterface;

		private final IDLTKSearchScope fScope;

		private final boolean fIsWorkspaceScope;

		private final int fElemKind;

		private final ITypeInfoFilterExtension fFilterExt;

		private final TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter();

		private SearchPattern fPackageMatcher;

		private boolean fMatchEverything = false;

		private final int fMyTypeFilterVersion = fTypeFilterVersion;

		/**
		 * Creates instance of TypeItemsFilter
		 *
		 * @param scope
		 * @param elementKind
		 * @param extension
		 */
		public TypeItemsFilter(IDLTKSearchScope scope, int elementKind, ITypeInfoFilterExtension extension) {
			super(new TypeSearchPattern());
			fScope = scope;
			fIsWorkspaceScope = scope == null ? false : scope.equals(SearchEngine.createWorkspaceScope(fToolkit));
			fElemKind = elementKind;
			fFilterExt = extension;
			String stringPackage = ((TypeSearchPattern) patternMatcher).getPackagePattern();
			if (stringPackage != null) {
				fPackageMatcher = new SearchPattern();
				fPackageMatcher.setPattern(stringPackage);
			} else {
				fPackageMatcher = null;
			}
		}

		@Override
		public boolean isSubFilter(ItemsFilter filter) {
			if (!super.isSubFilter(filter))
				return false;
			TypeItemsFilter typeItemsFilter = (TypeItemsFilter) filter;
			if (fScope != typeItemsFilter.getSearchScope())
				return false;
			if (fMyTypeFilterVersion != typeItemsFilter.getMyTypeFilterVersion())
				return false;
			return getPattern().indexOf('.', filter.getPattern().length()) == -1;
		}

		@Override
		public boolean equalsFilter(ItemsFilter iFilter) {
			if (!super.equalsFilter(iFilter))
				return false;
			if (!(iFilter instanceof TypeItemsFilter))
				return false;
			TypeItemsFilter typeItemsFilter = (TypeItemsFilter) iFilter;
			if (fScope != typeItemsFilter.getSearchScope())
				return false;
			if (fMyTypeFilterVersion != typeItemsFilter.getMyTypeFilterVersion())
				return false;
			return true;
		}

		public int getElementKind() {
			return fElemKind;
		}

		public IDLTKSearchScope getSearchScope() {
			return fScope;
		}

		public int getMyTypeFilterVersion() {
			return fMyTypeFilterVersion;
		}

		public String getPackagePattern() {
			if (fPackageMatcher == null)
				return null;
			return fPackageMatcher.getPattern();
		}

		public int getPackageFlags() {
			if (fPackageMatcher == null)
				return SearchPattern.RULE_EXACT_MATCH;

			return fPackageMatcher.getMatchRule();
		}

		public boolean matchesRawNamePattern(TypeNameMatch type) {
			return Strings.startsWithIgnoreCase(type.getSimpleTypeName(), getPattern());
		}

		public boolean matchesFilterExtension(TypeNameMatch type) {
			if (fFilterExt == null)
				return true;
			fAdapter.setMatch(type);
			return fFilterExt.select(fAdapter);
		}

		private boolean matchesName(TypeNameMatch type) {
			return matches(type.getSimpleTypeName());
		}

		private boolean matchesPackage(TypeNameMatch type) {
			if (fPackageMatcher == null)
				return true;
			return fPackageMatcher.matches(type.getPackageName());
		}

		private boolean matchesScope(TypeNameMatch type) {
			if (fIsWorkspaceScope)
				return true;
			return fScope.encloses(type.getType());

		}

		private boolean matchesModifiers(TypeNameMatch type) {
			if (fElemKind == IDLTKSearchConstants.TYPE)
				return true;
			int modifiers = type.getModifiers() & TYPE_MODIFIERS;
			switch (fElemKind) {
			case IDLTKSearchConstants.TYPE:
				return modifiers == 0;
			case IDLTKSearchConstants.ANNOTATION_TYPE:
				// return Flags.isAnnotation(modifiers);
				return false;
			}
			return false;
		}

		/**
		 * Set filter to "match everything" mode.
		 *
		 * @param matchEverything if <code>true</code>, {@link #matchItem(Object)}
		 *                        always returns true. If <code>false</code>, the filter
		 *                        is enabled.
		 */
		public void setMatchEverythingMode(boolean matchEverything) {
			this.fMatchEverything = matchEverything;
		}

		@Override
		public boolean isConsistentItem(Object item) {
			return true;
		}

		@Override
		public boolean matchItem(Object item) {

			if (fMatchEverything)
				return true;

			TypeNameMatch type = (TypeNameMatch) item;
			if (!(matchesPackage(type) && matchesModifiers(type) && matchesScope(type) && matchesFilterExtension(type)))
				return false;
			return matchesName(type);
		}

		@Override
		public boolean matchesRawNamePattern(Object item) {
			TypeNameMatch type = (TypeNameMatch) item;
			return matchesRawNamePattern(type);
		}

	}

	/**
	 * Extends functionality of SearchPatterns
	 */
	private static class TypeSearchPattern extends SearchPattern {

		private String packagePattern;

		@Override
		public void setPattern(String stringPattern) {
			String pattern = stringPattern;
			String packPattern = null;
			int index = stringPattern.lastIndexOf("."); //$NON-NLS-1$
			if (index != -1) {
				packPattern = evaluatePackagePattern(stringPattern.substring(0, index));
				pattern = stringPattern.substring(index + 1);
				if (pattern.length() == 0)
					pattern = "**"; //$NON-NLS-1$
			}
			super.setPattern(pattern);
			packagePattern = packPattern;
		}

		/*
		 * Transforms o.e.j to o.e.j
		 */
		private String evaluatePackagePattern(String s) {
			StringBuffer buf = new StringBuffer();
			boolean hasWildCard = false;
			for (int i = 0; i < s.length(); i++) {
				char ch = s.charAt(i);
				if (ch == '.') {
					if (!hasWildCard) {
						buf.append('*');
					}
					hasWildCard = false;
				} else if (ch == '*' || ch == '?') {
					hasWildCard = true;
				}
				buf.append(ch);
			}
			if (!hasWildCard) {
				buf.append('*');
			}
			return buf.toString();
		}

		@Override
		protected boolean isNameCharAllowed(char nameChar) {
			return super.isNameCharAllowed(nameChar);
		}

		@Override
		protected boolean isPatternCharAllowed(char patternChar) {
			return super.isPatternCharAllowed(patternChar);
		}

		@Override
		protected boolean isValidCamelCaseChar(char ch) {
			return super.isValidCamelCaseChar(ch);
		}

		/**
		 * @return the packagePattern
		 */
		public String getPackagePattern() {
			return packagePattern;
		}

	}

	/**
	 * A <code>TypeSearchRequestor</code> collects matches filtered using
	 * <code>TypeItemsFilter</code>. The attached content provider is filled on the
	 * basis of the collected entries (instances of <code>TypeNameMatch</code>).
	 */
	private class TypeSearchRequestor extends TypeNameMatchRequestor {
		private volatile boolean fStop;

		private final AbstractContentProvider fContentProvider;

		private final TypeItemsFilter fTypeItemsFilter;
		Set<String> addedNames = new HashSet<>();

		public TypeSearchRequestor(AbstractContentProvider contentProvider, TypeItemsFilter typeItemsFilter) {
			super();
			fContentProvider = contentProvider;
			fTypeItemsFilter = typeItemsFilter;
		}

		@Override
		public void acceptTypeNameMatch(TypeNameMatch match) {
			if (fStop)
				return;
			if (new TypeFilter(DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId())).isFiltered(match))
				return;
			if (!addedNames.contains(match.getTypeQualifiedName())) {
				addedNames.add(match.getTypeQualifiedName());
				if (fTypeItemsFilter.matchesFilterExtension(match))
					fContentProvider.add(match, fTypeItemsFilter);
			}
		}
	}

	/**
	 * Compares TypeItems is used during sorting
	 */
	private class TypeItemsComparator implements Comparator<TypeNameMatch> {

		private final Map<String, String> fLib2Name = new HashMap<>();

		private final String[] fInstallLocations;

		private final String[] fVMNames;

		/**
		 * Creates new instance of TypeItemsComparator
		 */
		public TypeItemsComparator() {
			List<String> locations = new ArrayList<>();
			List<String> labels = new ArrayList<>();
			IInterpreterInstallType[] installs = ScriptRuntime.getInterpreterInstallTypes();
			for (int i = 0; i < installs.length; i++) {
				processVMInstallType(installs[i], locations, labels);
			}
			fInstallLocations = locations.toArray(new String[locations.size()]);
			fVMNames = labels.toArray(new String[labels.size()]);
		}

		private void processVMInstallType(IInterpreterInstallType installType, List<String> locations,
				List<String> labels) {
			if (installType != null) {
				IInterpreterInstall[] installs = installType.getInterpreterInstalls();
				boolean isMac = Platform.OS_MACOSX.equals(Platform.getOS());
				final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$
				for (int i = 0; i < installs.length; i++) {
					String label = getFormattedLabel(installs[i].getName());
					LibraryLocation[] libLocations = installs[i].getLibraryLocations();
					if (libLocations != null) {
						processLibraryLocation(libLocations, label);
					} else {
						String filePath = installs[i].getInstallLocation().toOSString();
						// on MacOS X install locations end in an additional
						// "/Home" segment; remove it
						if (isMac && filePath.endsWith(HOME_SUFFIX))
							filePath = filePath.substring(0, filePath.length() - HOME_SUFFIX.length() + 1);
						locations.add(filePath);
						labels.add(label);
					}
				}
			}
		}

		private void processLibraryLocation(LibraryLocation[] libLocations, String label) {
			for (int l = 0; l < libLocations.length; l++) {
				LibraryLocation location = libLocations[l];
				fLib2Name.put(location.getLibraryPath().toString(), label);
			}
		}

		private String getFormattedLabel(String name) {
			return NLS.bind(DLTKUIMessages.FilteredTypesSelectionDialog_library_name_format, name);
		}

		@Override
		public int compare(TypeNameMatch leftInfo, TypeNameMatch rightInfo) {

			int result = compareName(leftInfo.getSimpleTypeName(), rightInfo.getSimpleTypeName());
			if (result != 0)
				return result;
			result = compareTypeContainerName(leftInfo.getTypeContainerName(), rightInfo.getTypeContainerName());
			if (result != 0)
				return result;

			int leftCategory = getElementTypeCategory(leftInfo);
			int rightCategory = getElementTypeCategory(rightInfo);
			if (leftCategory < rightCategory)
				return -1;
			if (leftCategory > rightCategory)
				return +1;
			return compareContainerName(leftInfo, rightInfo);
		}

		private int compareName(String leftString, String rightString) {
			int result = leftString.compareToIgnoreCase(rightString);
			if (result != 0 || rightString.length() == 0) {
				return result;
			} else if (Strings.isLowerCase(leftString.charAt(0)) && !Strings.isLowerCase(rightString.charAt(0))) {
				return +1;
			} else if (Strings.isLowerCase(rightString.charAt(0)) && !Strings.isLowerCase(leftString.charAt(0))) {
				return -1;
			} else {
				return leftString.compareTo(rightString);
			}
		}

		private int compareTypeContainerName(String leftString, String rightString) {
			int leftLength = leftString.length();
			int rightLength = rightString.length();
			if (leftLength == 0 && rightLength > 0)
				return -1;
			if (leftLength == 0 && rightLength == 0)
				return 0;
			if (leftLength > 0 && rightLength == 0)
				return +1;
			return compareName(leftString, rightString);
		}

		private int compareContainerName(TypeNameMatch leftType, TypeNameMatch rightType) {
			return getContainerName(leftType).compareTo(getContainerName(rightType));
		}

		private String getContainerName(TypeNameMatch type) {
			IProjectFragment root = type.getProjectFragment();
			if (root.isExternal()) {
				String name = root.getPath().toOSString();
				for (int i = 0; i < fInstallLocations.length; i++) {
					if (name.startsWith(fInstallLocations[i])) {
						return fVMNames[i];
					}
				}
				String lib = fLib2Name.get(name);
				if (lib != null)
					return lib;
			}
			StringBuffer buf = new StringBuffer();
			ScriptElementLabels labels = getUIToolkit().getScriptElementLabels();
			labels.getProjectFragmentLabel(root, ScriptElementLabels.ROOT_QUALIFIED | ScriptElementLabels.ROOT_VARIABLE,
					buf);
			return buf.toString();
		}

		private int getElementTypeCategory(TypeNameMatch type) {
			try {
				if (type.getProjectFragment().getKind() == IProjectFragment.K_SOURCE)
					return 0;
			} catch (ModelException e) {
				DLTKUIPlugin.log(e);
			}
			return 1;
		}
	}

	private IDLTKUILanguageToolkit getUIToolkit() {
		return DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId());
	}

	/**
	 * Extends the <code>SelectionHistory</code>, providing support for
	 * <code>OpenTypeHistory</code>.
	 */
	protected class TypeSelectionHistory extends SelectionHistory {

		/**
		 * Creates new instance of TypeSelectionHistory
		 */

		public TypeSelectionHistory() {
			super();
		}

		@Override
		public synchronized void accessed(Object object) {
			super.accessed(object);
		}

		@Override
		public synchronized boolean remove(Object element) {
			OpenTypeHistory.getInstance(getUIToolkit()).remove((TypeNameMatch) element);
			return super.remove(element);
		}

		@Override
		public void load(IMemento memento) {
			TypeNameMatch[] types = OpenTypeHistory.getInstance(getUIToolkit()).getTypeInfos();

			for (int i = 0; i < types.length; i++) {
				TypeNameMatch type = types[i];
				accessed(type);
			}
		}

		@Override
		public void save(IMemento memento) {
			persistHistory();
		}

		/**
		 * Stores contents of the local history into persistent history container.
		 */
		private synchronized void persistHistory() {
			if (getReturnCode() == OK) {
				Object[] items = getHistoryItems();
				for (int i = 0; i < items.length; i++) {
					OpenTypeHistory.getInstance(getUIToolkit()).accessed((TypeNameMatch) items[i]);
				}
			}
		}

		@Override
		protected Object restoreItemFromMemento(IMemento element) {
			return null;
		}

		@Override
		protected void storeItemToMemento(Object item, IMemento element) {

		}

	}

}
