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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;

import org.eclipse.compare.internal.CompareContainer;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.internal.ResizableDialog;
import org.eclipse.compare.internal.StructureCreatorDescriptor;
import org.eclipse.compare.internal.Utilities;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.compare.structuremergeviewer.IStructureComparator;
import org.eclipse.compare.structuremergeviewer.IStructureCreator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
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.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.util.Calendar;


/**
 * A dialog where one input element can be compared against
 * a list of historic variants (editions) of the same input element.
 * The dialog can be used to implement functions like "Compare/Replace with Version" or
 * "Compare/Replace from Local History" on workspace resources.
 * <p>
 * In addition it is possible to specify a subsection of the input element
 * (e.g. a method in a Java source file) by means of a "path".
 * In this case the dialog compares only the subsection (as specified by the path)
 * with the corresponding subsection in the list of editions.
 * Only those editions are shown where the subsection differs from the same subsection in
 * another edition thereby minimizing the number of presented variants.
 * This functionality can be used to implement "Replace from Local History"
 * for the Java language.
 * <p>
 * Subsections of an input element are determined by first finding an
 * <code>IStructureCreator</code> for the input's type.
 * Then the method <code>locate</code> is used to extract the subsection.
 * <p>
 * Each edition (variant in the list of variants) must implement the <code>IModificationDate</code> interface
 * so that the dialog can sort the editions and present them in a tree structure where every
 * node corresponds one day.
 * <p>
 * The functionality is surfaced in a single function <code>selectEdition</code>.
 * <p>
 * Clients may instantiate this class; it is not intended to be subclassed.
 * </p>
 *
 * @see IModificationDate
 * @see ITypedElement
 *
 * @deprecated Use an <code>org.eclipse.team.ui.history.IHistoryPageSource</code> in conjunction with
 * the <code>org.eclipse.team.ui.history.IHistoryView</code> or a <code>HistoryPageCompareEditorInput</code>.
 * For sub-file elements, a <code>org.eclipse.team.ui.history.ElementLocalHistoryPageSource</code> can be used.
 * @noextend This class is not intended to be subclassed by clients.
 */
@Deprecated
public class EditionSelectionDialog extends ResizableDialog {

	/**
	 * An item in an underlying edition.
	 */
	private static class Pair {

		private ITypedElement fEdition;
		private ITypedElement fItem;
		private String fContent;
		private IStructureCreator fStructureCreator;
		private boolean fHasError= false;

		Pair(IStructureCreator structureCreator, ITypedElement edition, ITypedElement item) {
			fStructureCreator= structureCreator;
			fEdition= edition;
			fItem= item;
		}

		Pair(IStructureCreator structureCreator, ITypedElement edition) {
			this(structureCreator, edition, edition);
		}

		ITypedElement getEdition() {
			return fEdition;
		}

		ITypedElement getItem() {
			return fItem;
		}

		/*
		 * The content is lazily loaded
		 */
		private String getContent() {
			if (fContent == null) {
				if (fStructureCreator != null)
					fContent= fStructureCreator.getContents(fItem, false);
				else {
					if (fItem instanceof IStreamContentAccessor) {
						IStreamContentAccessor sca= (IStreamContentAccessor) fItem;
						try {
							fContent= Utilities.readString(sca);
						} catch (CoreException ex) {
							// NeedWork
							CompareUIPlugin.log(ex);
						}
					}
				}
				if (fContent == null)
					fContent= ""; //$NON-NLS-1$
			}
			return fContent;
		}

		@Override
		public boolean equals(Object other) {
			if (other != null && other.getClass() == getClass()) {
				if (getContent().equals(((Pair)other).getContent()))
					return true;
			}
			return super.equals(other);
		}

		@Override
		public int hashCode() {
			return getContent().hashCode();
		}
	}

	// Configuration options
	private CompareConfiguration fCompareConfiguration;
	private ArrayList<Object> fArrayList= new ArrayList<>();
	/** use a side-by-side compare viewer */
	private boolean fCompare= true;
	/** show target on right hand side */
	private boolean fTargetIsRight= false;
	/** hide entries which have identical content */
	private boolean fHideIdentical= true;
	/** add mode if true, otherwise replace mode */
	private boolean fAddMode= false;
	/** compare mode if true, otherwise replace/add mode */
	private boolean fCompareMode= false;
	/** perform structure compare on editions */
	private boolean fStructureCompare= false;
	/** allow for multiple selection */
	private boolean fMultiSelect= false;

	/**
	 * Maps from members to their corresponding editions.
	 * Has only a single entry if dialog is used in "Replace" (and not "Add") mode.
	 */
	private HashMap<ITypedElement, List<Pair>> fMemberEditions;
	/**
	 * Maps from members to their corresponding selected edition.
	 */
	private HashMap<List, ITypedElement> fMemberSelection;
	/** The editions of the current selected member */
	private List fCurrentEditions;
	private Thread fThread;
	private Pair fTargetPair;
	/** The selected edition in the edition viewer */
	private ITypedElement fSelectedItem;
	private String fTitleArg;
	private Image fTitleImage;

	// SWT controls
	private CompareViewerSwitchingPane fContentPane;
	private Button fCommitButton;
	private Table fMemberTable;
	private CompareViewerPane fMemberPane;
	private Tree fEditionTree;
	private CompareViewerPane fEditionPane;
	private Image fDateImage;
	private Image fTimeImage;
	private CompareViewerSwitchingPane fStructuredComparePane;
	private Label statusLabel;

	/**
	 * Creates a new modal, resizable dialog.
	 * Various titles, icons, and labels are configured from the given resource bundle.
	 * The following resource keys are used:
	 * <pre>
	 *	key         type          description
	 *	title       String        dialog title
	 *	width       Integer       initial width of dialog
	 *	height      Integer       initial height of dialog
	 *	treeTitleFormat   MessageFormat pane title for edition tree; arg 0 is the target
	 *	dateIcon    String        icon for node in edition tree; path relative to plug-in
	 *	timeIcon    String        icon for leaf in edition tree; path relative to plug-in
	 *	todayFormat MessageFormat format string if date is todays date; arg 0 is date
	 *	yesterdayFormat MessageFormat format string if date is yesterdays date; arg 0 is date
	 *	dayFormat   MessageFormat format string if date is any other date; arg 0 is date
	 *	editionLabel String       label for editions side of compare viewer; arg 0 is the date
	 *	targetLabel  String       label for target side of compare viewer
	 *  buttonLabel  String       label for OK button; default is IDialogConstants.OK_LABEL
	 * </pre>
	 *
	 * @param parent if not <code>null</code> the new dialog stays on top of this parent shell
	 * @param bundle <code>ResourceBundle</code> to configure the dialog
	 */
	public EditionSelectionDialog(Shell parent, ResourceBundle bundle) {
		super(parent, bundle);
	}

	private CompareConfiguration getCompareConfiguration() {
		if (fCompareConfiguration == null) {
			fCompareConfiguration= new CompareConfiguration();
			fCompareConfiguration.setLeftEditable(false);
			fCompareConfiguration.setRightEditable(false);
			fCompareConfiguration.setContainer(new CompareContainer() {
				@Override
				public void setStatusMessage(String message) {
					if (statusLabel != null && !statusLabel.isDisposed()) {
						if (message == null) {
							statusLabel.setText(""); //$NON-NLS-1$
						} else {
							statusLabel.setText(message);
						}
					}
				}
			});
		}
		return fCompareConfiguration;
	}

	/**
	 * Sets the help context for this dialog.
	 *
	 * @param contextId the help context id.
	 * @since 3.2
	 */
	@Override
	public void setHelpContextId(String contextId) {
		super.setHelpContextId(contextId);
	}

	/**
	 * Sets an additional and optional argument for the edition pane's title.
	 *
	 * @param titleArgument an optional argument for the edition pane's title
	 * @since 2.0
	 */
	public void setEditionTitleArgument(String titleArgument) {
		fTitleArg= titleArgument;
	}

	/**
	 * Sets an optional image for the edition pane's title.
	 *
	 * @param titleImage an optional image for the edition pane's title
	 * @since 2.0
	 */
	public void setEditionTitleImage(Image titleImage) {
		fTitleImage= titleImage;
	}

	/**
	 * Select the previous edition (presenting a UI).
	 *
	 * @param target the input object against which the editions are compared; must not be <code>null</code>
	 * @param inputEditions the list of editions (element type: <code>ITypedElement</code>s)
	 * @param ppath If <code>null</code> dialog shows full input; if non <code>null</code> it extracts a subsection
	 * @return returns the selected edition or <code>null</code> if error occurred.
	 * The returned <code>ITypedElement</code> is one of the original editions
	 * if <code>path</code> was <code>null</code>; otherwise
	 * it is an <code>ITypedElement</code> returned from <code>IStructureCreator.locate(path, item)</code>
	 * @since 2.0
	 */
	public ITypedElement selectPreviousEdition(final ITypedElement target, ITypedElement[] inputEditions, Object ppath) {
		Assert.isNotNull(target);
		fTargetPair= new Pair(null, target);

		// sort input editions
		final int count= inputEditions.length;
		final IModificationDate[] editions= new IModificationDate[count];
		for (int i= 0; i < count; i++)
			editions[i]= (IModificationDate) inputEditions[i];
		if (count > 1)
			internalSort(editions);

		// find StructureCreator if ppath is not null
		IStructureCreator structureCreator= null;
		if (ppath != null) {
			String type= target.getType();
			StructureCreatorDescriptor scd= CompareUIPlugin.getDefault().getStructureCreator(type);
			if (scd != null)
				structureCreator= scd.createStructureCreator();
		}

		if (fAddMode) {
			// does not work in add mode
			return null;
		}

		if (structureCreator != null) {
			Pair pair= createPair(structureCreator, ppath, target);
			if (pair != null)
				fTargetPair= pair;
			else
				ppath= null;	// couldn't extract item because of error
		}

		// from front (newest) to back (oldest)
		for (int i= 0; i < count; i++) {

			ITypedElement edition= (ITypedElement) editions[i];
			Pair pair= null;

			if (structureCreator != null && ppath != null) {
				// extract sub element from edition
				pair= createPair(structureCreator, ppath, edition);
			} else {
				pair= new Pair(null, edition);
			}

			if (pair != null && pair.fHasError)
				return null;

			if (pair != null && !fTargetPair.equals(pair)) {
				return pair.fItem;
			}
		}

		// nothing found
		return null;
	}

	/**
	 * Presents this modal dialog with the functionality described in the class comment above.
	 *
	 * @param target the input object against which the editions are compared; must not be <code>null</code>
	 * @param inputEditions the list of editions (element type: <code>ITypedElement</code>s)
	 * @param ppath If <code>null</code> dialog shows full input; if non <code>null</code> it extracts a subsection
	 * @return returns the selected edition or <code>null</code> if dialog was cancelled.
	 * The returned <code>ITypedElement</code> is one of the original editions
	 * if <code>path</code> was <code>null</code>; otherwise
	 * it is an <code>ITypedElement</code> returned from <code>IStructureCreator.locate(path, item)</code>
	 */
	public ITypedElement selectEdition(final ITypedElement target, ITypedElement[] inputEditions, Object ppath) {

		Assert.isNotNull(target);
		fTargetPair= new Pair(null, target);

		// sort input editions
		final int count= inputEditions.length;
		final IModificationDate[] editions= new IModificationDate[count];
		for (int i= 0; i < count; i++)
			editions[i]= (IModificationDate) inputEditions[i];
		if (count > 1)
			internalSort(editions);

		// find StructureCreator if ppath is not null
		IStructureCreator structureCreator= null;
		if (ppath != null) {
			String type= target.getType();
			StructureCreatorDescriptor scd= CompareUIPlugin.getDefault().getStructureCreator(type);
			if (scd != null)
				structureCreator= scd.createStructureCreator();
		}

		if (!fAddMode) {
			// replace mode

			if (structureCreator != null) {
				Pair pair= createPair(structureCreator, ppath, target);
				if (pair != null)
					fTargetPair= pair;
				else
					ppath= null;	// couldn't extract item because of error
			}

			// set the left and right labels for the compare viewer
			String targetLabel= getTargetLabel(target, fTargetPair.getItem());
			if (fTargetIsRight)
				getCompareConfiguration().setRightLabel(targetLabel);
			else
				getCompareConfiguration().setLeftLabel(targetLabel);

			if (structureCreator != null && ppath != null) {	// extract sub element

				final IStructureCreator sc= structureCreator;
				final Object path= ppath;

				// construct the comparer thread
				// and perform the background extract
				fThread= new Thread() {
					@Override
					public void run() {

						// from front (newest) to back (oldest)
						for (int i= 0; i < count; i++) {

							if (fEditionTree == null || fEditionTree.isDisposed())
								break;
							ITypedElement edition= (ITypedElement) editions[i];

							// extract sub element from edition
							Pair pair= createPair(sc, path, edition);
							if (pair != null)
								sendPair(pair);
						}
						sendPair(null);
					}
				};
			} else {
				// create tree widget
				create();

				// from front (newest) to back (oldest)
				for (int i= 0; i < count; i++)
					addMemberEdition(new Pair(null, (ITypedElement) editions[i]));
			}

		} else {
			// add mode
			final Object container= ppath;
			Assert.isNotNull(container);

			if (structureCreator == null)
				return null;	// error

			// extract all elements of container
			final HashSet<Object> current= new HashSet<>();
			IStructureComparator sco= structureCreator.locate(container, target);
			if (sco != null) {
				Object[] children= sco.getChildren();
				if (children != null)
					for (int i= 0; i < children.length; i++)
						current.add(children[i]);
			}

			final IStructureCreator sc= structureCreator;

			// construct the comparer thread
			// and perform the background extract
			fThread= new Thread() {
				@Override
				public void run() {

					// from front (newest) to back (oldest)
					for (int i= 0; i < count; i++) {

						if (fEditionTree == null || fEditionTree.isDisposed())
							break;
						ITypedElement edition= (ITypedElement) editions[i];

						IStructureComparator sco2= sc.locate(container, edition);
						if (sco2 != null) {
							Object[] children= sco2.getChildren();
							if (children != null) {
								for (int i2= 0; i2 < children.length; i2++) {
									ITypedElement child= (ITypedElement) children[i2];
									if (!current.contains(child))
										sendPair(new Pair(sc, edition, child));
								}
							}
						}
					}
					sendPair(null);
				}
			};
		}

		open();

		if (getReturnCode() == OK)
			return fSelectedItem;
		return null;
	}

	private Pair createPair(IStructureCreator sc, Object path, ITypedElement input) {
		IStructureComparator scmp= sc.locate(path, input);
		if (scmp == null && sc.getStructure(input) == null) {	// parse error
			Pair p= new Pair(sc, input);
			p.fHasError= true;
			return p;
		}
		if (scmp instanceof ITypedElement)
			return new Pair(sc, input, (ITypedElement) scmp);
		return null;
	}

	/**
	 * Controls whether identical entries are shown or not (default).
	 * This method must be called before <code>selectEdition</code>.
	 *
	 * @param hide if true identical entries are hidden; otherwise they are shown.
	 * @since 2.0
	 */
	public void setHideIdenticalEntries(boolean hide) {
		fHideIdentical= hide;
	}

	/**
	 * Controls whether workspace target is on the left (the default) or right hand side.
	 *
	 * @param isRight if true target is shown on right hand side.
	 * @since 2.0
	 */
	public void setTargetIsRight(boolean isRight) {
		fTargetIsRight= isRight;
	}

	/**
	 * Controls whether the <code>EditionSelectionDialog</code> is in 'add' mode
	 * or 'replace' mode (the default).
	 *
	 * @param addMode if true dialog is in 'add' mode.
	 * @since 2.0
	 */
	public void setAddMode(boolean addMode) {
		fAddMode= addMode;
		fMultiSelect= addMode;
	}

	/**
	 * Controls whether the <code>EditionSelectionDialog</code> is in 'compare' mode
	 * or 'add/replace' (the default) mode.
	 *
	 * @param compareMode if true dialog is in 'add' mode.
	 * @since 2.0
	 */
	public void setCompareMode(boolean compareMode) {
		fCompareMode= compareMode;
		fStructureCompare= fCompareMode && !fAddMode;
	}

	/**
	 * Returns the input target that has been specified with the most recent call
	 * to <code>selectEdition</code>. If a not <code>null</code> path was specified this method
	 * returns a subsection of this target (<code>IStructureCreator.locate(path, target)</code>)
	 * instead of the input target.
	 * <p>
	 * For example if the <code>target</code> is a Java compilation unit and <code>path</code> specifies
	 * a method, the value returned from <code>getTarget</code> will be the method not the compilation unit.
	 *
	 * @return the last specified target or a subsection thereof.
	 */
	public ITypedElement getTarget() {
		return fTargetPair.getItem();
	}

	/**
	 * Returns the editions that have been selected with the most
	 * recent call to <code>selectEdition</code>.
	 *
	 * @return the selected editions as an array.
	 * @since 2.1
	 */
	public ITypedElement[] getSelection() {
		ArrayList<ITypedElement> result= new ArrayList<>();
		if (fMemberSelection != null) {
			Iterator<Object> iter= fArrayList.iterator();
			while (iter.hasNext()) {
				Object edition= iter.next();
				Object item= fMemberSelection.get(edition);
				if (item != null)
					result.add((ITypedElement) item);
			}
		} else if (fSelectedItem != null)
			result.add(fSelectedItem);
		return result.toArray(new ITypedElement[result.size()]);
	}

	/**
	 * Returns a label for identifying the target side of a compare viewer.
	 * This implementation extracts the value for the key "targetLabel" from the resource bundle
	 * and passes it as the format argument to <code>MessageFormat.format</code>.
	 * The single format argument for <code>MessageFormat.format</code> ("{0}" in the format string)
	 * is the name of the given input element.
	 * <p>
	 * Subclasses may override to create their own label.
	 * </p>
	 *
	 * @param target the target element for which a label must be returned
	 * @param item if a path has been specified in <code>selectEdition</code> a sub element of the given target; otherwise the same as target
	 * @return a label the target side of a compare viewer
	 */
	protected String getTargetLabel(ITypedElement target, ITypedElement item) {
		String format= null;
		if (target instanceof ResourceNode)
			format= Utilities.getString(fBundle, "workspaceTargetLabel", null); //$NON-NLS-1$
		if (format == null)
			format= Utilities.getString(fBundle, "targetLabel"); //$NON-NLS-1$
		if (format == null)
			format= "x{0}"; //$NON-NLS-1$

		return formatString(format, target.getName());
	}

	private String formatString(String string, String variable) {
		// Only process the string if it contains a variable or an escaped quote (see bug 190023)
		if (hasVariable(string) || hasDoubleQuotes(string))
			return MessageFormat.format(string, variable);
		return string;
	}

	private boolean hasDoubleQuotes(String string) {
		return string.indexOf("''") != -1; //$NON-NLS-1$
	}

	private boolean hasVariable(String string) {
		return string.indexOf("{0}") != -1; //$NON-NLS-1$
	}

	/**
	 * Returns a label for identifying the edition side of a compare viewer.
	 * This implementation extracts the value for the key "editionLabel" from the resource bundle
	 * and passes it as the format argument to <code>MessageFormat.format</code>.
	 * The single format argument for <code>MessageFormat.format</code> ("{0}" in the format string)
	 * is the formatted modification date of the given input element.
	 * <p>
	 * Subclasses may override to create their own label.
	 * </p>
	 *
	 * @param selectedEdition the selected edition for which a label must be returned
	 * @param item if a path has been specified in <code>selectEdition</code> a sub element of the given selectedEdition; otherwise the same as selectedEdition
	 * @return a label for the edition side of a compare viewer
	 */
	protected String getEditionLabel(ITypedElement selectedEdition, ITypedElement item) {
		String format= null;
		if (selectedEdition instanceof ResourceNode)
			format= Utilities.getString(fBundle, "workspaceEditionLabel", null);	//$NON-NLS-1$
		else if (selectedEdition instanceof HistoryItem)
			format= Utilities.getString(fBundle, "historyEditionLabel", null);	//$NON-NLS-1$
		if (format == null)
			format= Utilities.getString(fBundle, "editionLabel");	//$NON-NLS-1$
		if (format == null)
			format= "x{0}";	//$NON-NLS-1$


		String date= "";	//$NON-NLS-1$
		if (selectedEdition instanceof IModificationDate) {
			long modDate= ((IModificationDate)selectedEdition).getModificationDate();
			date= DateFormat.getDateTimeInstance().format(new Date(modDate));
		}

		return formatString(format, date);
	}

	/**
	 * Returns a label for identifying a node in the edition tree viewer.
	 * This implementation extracts the value for the key "workspaceTreeFormat" or
	 * "treeFormat" (in that order) from the resource bundle
	 * and passes it as the format argument to <code>MessageFormat.format</code>.
	 * The single format argument for <code>MessageFormat.format</code> ("{0}" in the format string)
	 * is the formatted modification date of the given input element.
	 * <p>
	 * Subclasses may override to create their own label.
	 * </p>
	 *
	 * @param edition the edition for which a label must be returned
	 * @param item if a path has been specified in <code>edition</code> a sub element of the given edition; otherwise the same as edition
	 * @param date this date will be returned as part of the formatted string
	 * @return a label of a node in the edition tree viewer
	 * @since 2.0
	 */
	protected String getShortEditionLabel(ITypedElement edition, ITypedElement item, Date date) {
		String format= null;
		if (edition instanceof ResourceNode)
			format= Utilities.getString(fBundle, "workspaceTreeFormat", null);	//$NON-NLS-1$
		if (format == null)
			format= Utilities.getString(fBundle, "treeFormat", null);	//$NON-NLS-1$
		if (format == null)
			format= "x{0}"; //$NON-NLS-1$

		String ds= DateFormat.getTimeInstance().format(date);
		return formatString(format, ds);
	}

	/**
	 * Returns an image for identifying the edition side of a compare viewer.
	 * This implementation extracts the value for the key "editionLabel" from the resource bundle
	 * and passes it as the format argument to <code>MessageFormat.format</code>.
	 * The single format argument for <code>MessageFormat.format</code> ("{0}" in the format string)
	 * is the formatted modification date of the given input element.
	 * <p>
	 * Subclasses may override to create their own label.
	 * </p>
	 *
	 * @param selectedEdition the selected edition for which a label must be returned
	 * @param item if a path has been specified in <code>selectEdition</code> a sub element of the given selectedEdition; otherwise the same as selectedEdition
	 * @return a label the edition side of a compare viewer
	 * @since 2.0
	 */
	protected Image getEditionImage(ITypedElement selectedEdition, ITypedElement item) {
		if (selectedEdition instanceof ResourceNode)
			return selectedEdition.getImage();
		if (selectedEdition instanceof HistoryItem) {
			if (fTimeImage == null) {
				String iconName= Utilities.getString(fBundle, "timeIcon", "obj16/resource_obj.png"); //$NON-NLS-1$ //$NON-NLS-2$
				ImageDescriptor id= CompareUIPlugin.getImageDescriptor(iconName);
				if (id != null)
					fTimeImage= id.createImage();
			}
			return fTimeImage;
		}
		return null;
	}

	@Override
	protected synchronized Control createDialogArea(Composite parent2) {

		Composite parent= (Composite) super.createDialogArea(parent2);

		getShell().setText(Utilities.getString(fBundle, "title")); //$NON-NLS-1$

		Splitter vsplitter= new Splitter(parent,  SWT.VERTICAL);
		vsplitter.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL
					| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));

		vsplitter.addDisposeListener(
			e -> {
				if (fCompareConfiguration != null) {
					fCompareConfiguration.dispose();
					fCompareConfiguration= null;
				}
				if (fDateImage != null) {
					fDateImage.dispose();
					fDateImage= null;
				}
				if (fTimeImage != null) {
					fTimeImage.dispose();
					fTimeImage= null;
				}
			}
		);

		if (fAddMode) {
			// we need two panes: the left for the elements, the right one for the editions
			Splitter hsplitter= new Splitter(vsplitter,  SWT.HORIZONTAL);

			fMemberPane= new CompareViewerPane(hsplitter, SWT.BORDER | SWT.FLAT);
			fMemberPane.setText(Utilities.getString(fBundle, "memberPaneTitle")); //$NON-NLS-1$

			int flags= SWT.H_SCROLL | SWT.V_SCROLL;
			if (fMultiSelect)
				flags|= SWT.CHECK;
			fMemberTable= new Table(fMemberPane, flags);
			fMemberTable.addSelectionListener(
				new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						if (e.detail == SWT.CHECK) {
							if (e.item instanceof TableItem) {
								TableItem ti= (TableItem) e.item;
								Object data= ti.getData();
								if (ti.getChecked())
									fArrayList.add(data);
								else
									fArrayList.remove(data);

								if (fCommitButton != null)
									fCommitButton.setEnabled(fArrayList.size() > 0);

								fMemberTable.setSelection(new TableItem[] { ti });
							}
						}
						handleMemberSelect(e.item);
					}
				}
			);
			fMemberPane.setContent(fMemberTable);
			fMemberTable.setFocus();

			fEditionPane= new CompareViewerPane(hsplitter, SWT.BORDER | SWT.FLAT);
		} else {
			if (fStructureCompare) {
				// we need two panes: the left for the elements, the right one for the structured diff
				Splitter hsplitter= new Splitter(vsplitter,  SWT.HORIZONTAL);

				fEditionPane= new CompareViewerPane(hsplitter, SWT.BORDER | SWT.FLAT);
				fStructuredComparePane= new CompareViewerSwitchingPane(hsplitter, SWT.BORDER | SWT.FLAT, true) {
					@Override
					protected Viewer getViewer(Viewer oldViewer, Object input) {
						if (input instanceof ICompareInput)
							return CompareUI.findStructureViewer(oldViewer, (ICompareInput)input, this, getCompareConfiguration());
						return null;
					}
				};
				fStructuredComparePane.addSelectionChangedListener(
					e -> feedInput2(e.getSelection())
				);
			} else {
				// only a single pane showing the editions
				fEditionPane= new CompareViewerPane(vsplitter, SWT.BORDER | SWT.FLAT);
			}
			if (fTitleArg == null)
				fTitleArg= fTargetPair.getItem().getName();
			String titleFormat= Utilities.getString(fBundle, "treeTitleFormat"); //$NON-NLS-1$
			String title= MessageFormat.format(titleFormat, fTitleArg );
			fEditionPane.setText(title);
			if (fTitleImage != null)
				fEditionPane.setImage(fTitleImage);
		}

		fEditionTree= new Tree(fEditionPane, SWT.H_SCROLL | SWT.V_SCROLL);
		fEditionTree.addSelectionListener(
			new SelectionAdapter() {
//				public void widgetDefaultSelected(SelectionEvent e) {
//					handleDefaultSelected();
//				}
				@Override
				public void widgetSelected(SelectionEvent e) {
					feedInput(e.item);
				}
			}
		);
		fEditionPane.setContent(fEditionTree);

		// now start the thread (and forget about it)
		if (fThread != null) {
			fThread.start();
			fThread= null;
		}

		fContentPane= new CompareViewerSwitchingPane(vsplitter, SWT.BORDER | SWT.FLAT) {
			@Override
			protected Viewer getViewer(Viewer oldViewer, Object input) {
				return CompareUI.findContentViewer(oldViewer, input, this, getCompareConfiguration());
			}
		};
		vsplitter.setWeights(new int[] { 30, 70 });

		statusLabel = new Label(parent, SWT.NONE);
		statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		applyDialogFont(parent);
		return parent;
	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		String buttonLabel= Utilities.getString(fBundle, "buttonLabel", IDialogConstants.OK_LABEL); //$NON-NLS-1$
		if (fCompareMode) {
			// only a 'Done' button
			createButton(parent, IDialogConstants.CANCEL_ID, buttonLabel, false);
		} else {
			// a 'Cancel' and a 'Add/Replace' button
			fCommitButton= createButton(parent, IDialogConstants.OK_ID, buttonLabel, true);
			fCommitButton.setEnabled(false);
			createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
		}
	}

	/**
	 * Overidden to disable dismiss on double click in compare mode.
	 * @since 2.0
	 */
	@Override
	protected void okPressed() {
		if (fCompareMode) {
			// don't dismiss dialog
		} else
			super.okPressed();
	}

	//---- private stuff ----------------------------------------------------------------------------------------

	/*
	 * Asynchroneously sends a Pair (or null) to the UI thread.
	 */
	private void sendPair(final Pair pair) {
		if (fEditionTree != null && !fEditionTree.isDisposed()) {
			Display display= fEditionTree.getDisplay();
			display.asyncExec(
				() -> addMemberEdition(pair)
			);
		}
	}

	private static void internalSort(IModificationDate[] keys) {
		Arrays.sort(keys, (d1, d2) -> {
			long d= d2.getModificationDate() - d1.getModificationDate();
			if (d < 0)
				return -1;
			if (d > 0)
				return 1;
			return 0;
		});
	}

	/*
	 * Adds the given Pair to the member editions.
	 * If HIDE_IDENTICAL is true the new Pair is only added if its contents
	 * is different from the preceeding Pair.
	 * If the argument is <code>null</code> the message "No Editions found" is shown
	 * in the member or edition viewer.
	 */
	private void addMemberEdition(Pair pair) {

		if (pair == null) {	// end of list of pairs
			if (fMemberTable != null) {
				if (!fMemberTable.isDisposed() && fMemberTable.getItemCount() == 0) {
					if (fMultiSelect) {
						fMemberTable.dispose();
						fMemberTable= new Table(fMemberPane, SWT.NONE);
						fMemberPane.setContent(fMemberTable);
					}
					TableItem ti= new TableItem(fMemberTable, SWT.NONE);
					ti.setText(Utilities.getString(fBundle, "noAdditionalMembersMessage")); //$NON-NLS-1$
				}
				return;
			}
			if (fEditionTree != null && !fEditionTree.isDisposed() && fEditionTree.getItemCount() == 0) {
				TreeItem ti= new TreeItem(fEditionTree, SWT.NONE);
				ti.setText(Utilities.getString(fBundle, "notFoundInLocalHistoryMessage")); //$NON-NLS-1$
			}
			return;
		}

		if (fMemberEditions == null)
			fMemberEditions= new HashMap<>();
		if (fMultiSelect && fMemberSelection == null)
			fMemberSelection= new HashMap<>();

		ITypedElement item= pair.getItem();
		List<Pair> editions= fMemberEditions.get(item);
		if (editions == null) {
			editions= new ArrayList<>();
			fMemberEditions.put(item, editions);
			if (fMemberTable != null && !fMemberTable.isDisposed()) {
				ITypedElement te= item;
				String name= te.getName();

				// find position
				TableItem[] items= fMemberTable.getItems();
				int where= items.length;
				for (int i= 0; i < where; i++) {
					String n= items[i].getText();
					if (n.compareTo(name) > 0) {
						where= i;
						break;
					}
				}

				TableItem ti= new TableItem(fMemberTable, where, SWT.NULL);
				ti.setImage(te.getImage());
				ti.setText(name);
				ti.setData(editions);
			}
		}
		if (fHideIdentical) {
			Pair last= fTargetPair;
			int size= editions.size();
			if (size > 0)
				last= editions.get(size-1);
			if (last != null && last.equals(pair))
				return;	// don't add since the new one is equal to old
		}
		editions.add(pair);

		if (!fAddMode || editions == fCurrentEditions)
			addEdition(pair);
	}

	/*
	 * Returns the number of s since Jan 1st, 1970.
	 * The given date is converted to GMT and daylight saving is taken into account too.
	 */
	private long dayNumber(long date) {
		int ONE_DAY_MS= 24*60*60 * 1000; // one day in milli seconds

		Calendar calendar= Calendar.getInstance();
		long localTimeOffset= calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);

		return (date + localTimeOffset) / ONE_DAY_MS;
	}

	/*
	 * Adds the given Pair to the edition tree.
	 * It takes care of creating tree nodes for different dates.
	 */
	private void addEdition(Pair pair) {
		if (fEditionTree == null || fEditionTree.isDisposed())
			return;

		// find last day
		TreeItem[] days= fEditionTree.getItems();
		TreeItem lastDay= null;
		if (days.length > 0)
			lastDay= days[days.length-1];

		boolean first= lastDay == null;

		ITypedElement edition= pair.getEdition();
		ITypedElement item= pair.getItem();

		long ldate= ((IModificationDate)edition).getModificationDate();
		long day= dayNumber(ldate);
		Date date= new Date(ldate);
		if (lastDay == null || day != dayNumber(((Date)lastDay.getData()).getTime())) {
			lastDay= new TreeItem(fEditionTree, SWT.NONE);
			if (fDateImage == null) {
				String iconName= Utilities.getString(fBundle, "dateIcon", "obj16/day_obj.png"); //$NON-NLS-2$ //$NON-NLS-1$
				ImageDescriptor id= CompareUIPlugin.getImageDescriptor(iconName);
				if (id != null)
					fDateImage= id.createImage();
			}
			lastDay.setImage(fDateImage);
			String df= DateFormat.getDateInstance().format(date);
			long today= dayNumber(System.currentTimeMillis());

			String formatKey;
			if (day == today)
				formatKey= "todayFormat"; //$NON-NLS-1$
			else if (day == today-1)
				formatKey= "yesterdayFormat"; //$NON-NLS-1$
			else
				formatKey= "dayFormat"; //$NON-NLS-1$
			String pattern= Utilities.getString(fBundle, formatKey);
			if (pattern != null)
				df= MessageFormat.format(pattern, df);
			lastDay.setText(df);
			lastDay.setData(date);
		}
		TreeItem ti= new TreeItem(lastDay, SWT.NONE);
		ti.setImage(getEditionImage(edition, item));

		String s= getShortEditionLabel(edition, item, date);
		if (pair.fHasError) {
			String pattern= Utilities.getString(fBundle, "parseErrorFormat"); //$NON-NLS-1$
			s= MessageFormat.format(pattern, s);
		}
		ti.setText(s);

		ti.setData(pair);

		// determine selected TreeItem
		TreeItem selection= first ? ti : null;
		if (fMemberSelection != null) {
			Object selected= fMemberSelection.get(fCurrentEditions);
			if (selected != null) {
				if (selected == pair.getItem())
					selection= ti;
				else
					selection= null;
			}
		}
		if (selection != null) {
			fEditionTree.setSelection(new TreeItem[] { selection });
			if (!fAddMode)
				fEditionTree.setFocus();
			feedInput(selection);
		}

		if (first) // expand first node
			lastDay.setExpanded(true);
	}

	/*
	 * Feeds selection from member viewer to edition viewer.
	 */
	private void handleMemberSelect(Widget w) {
		Object data= w.getData();
		if (data instanceof List) {
			@SuppressWarnings("unchecked")
			List<Object> editions= (List<Object>) data;
			if (editions != fCurrentEditions) {
				fCurrentEditions= editions;
				fEditionTree.removeAll();

				String pattern= Utilities.getString(fBundle, "treeTitleFormat"); //$NON-NLS-1$
				String title= MessageFormat.format(pattern, new Object[] { ((Item)w).getText() });
				fEditionPane.setText(title);

				Iterator<Object> iter= editions.iterator();
				while (iter.hasNext()) {
					Object item= iter.next();
					if (item instanceof Pair)
						addEdition((Pair) item);
				}
			}
		}
	}

	private void setInput(Object input) {
		if (!fCompare && input instanceof ICompareInput) {
			ICompareInput ci= (ICompareInput) input;
			if (fTargetIsRight)
				input= ci.getLeft();
			else
				input= ci.getRight();
		}
		fContentPane.setInput(input);
		if (fStructuredComparePane != null)
			fStructuredComparePane.setInput(input);
	}

	/*
	 * Feeds selection from edition viewer to content (and structure) viewer.
	 */
	private void feedInput(Widget w) {
		Object input= w.getData();
		boolean isOK= false;
		if (input instanceof Pair) {
			Pair pair= (Pair) input;
			fSelectedItem= pair.getItem();
			isOK= !pair.fHasError;

			ITypedElement edition= pair.getEdition();
			String editionLabel= getEditionLabel(edition, fSelectedItem);
			Image editionImage= getEditionImage(edition, fSelectedItem);

			if (fAddMode) {
				if (fMemberSelection != null)
					fMemberSelection.put(fCurrentEditions, fSelectedItem);
				setInput(fSelectedItem);
				fContentPane.setText(editionLabel);
				fContentPane.setImage(editionImage);
			} else {
				getCompareConfiguration();
				if (fTargetIsRight) {
					fCompareConfiguration.setLeftLabel(editionLabel);
					fCompareConfiguration.setLeftImage(editionImage);
					setInput(new DiffNode(fSelectedItem, fTargetPair.getItem()));
				} else {
					fCompareConfiguration.setRightLabel(editionLabel);
					fCompareConfiguration.setRightImage(editionImage);
					setInput(new DiffNode(fTargetPair.getItem(), fSelectedItem));
				}
			}
		} else {
			fSelectedItem= null;
			setInput(null);
		}
		if (fCommitButton != null) {
			if (fMultiSelect)
				fCommitButton.setEnabled(isOK && fSelectedItem != null && fArrayList.size() > 0);
			else
				fCommitButton.setEnabled(isOK && fSelectedItem != null && fTargetPair.getItem() != fSelectedItem);
		}
	}

	/*
	 * Feeds selection from structure viewer to content viewer.
	 */
	private void feedInput2(ISelection sel) {
		if (sel instanceof IStructuredSelection) {
			IStructuredSelection ss= (IStructuredSelection) sel;
			if (ss.size() == 1)
				fContentPane.setInput(ss.getFirstElement());
		}
	}
}
