/*******************************************************************************
 * Copyright (c) 2011 WindRiver Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     WindRiver Corporation - initial API and implementation
 *     IBM Corporation - Ongoing development
 *     Ericsson AB (Pascal Rapicault) - Bug 387115 - Allow to export everything
 *     Ericsson AB (Hamdan Msheik) - Bug 398833, 402560
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration;

import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.*;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.preferences.*;
import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
import org.eclipse.equinox.internal.p2.ui.dialogs.*;
import org.eclipse.equinox.internal.p2.ui.model.*;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdatePlugin;
import org.eclipse.equinox.internal.p2.ui.viewers.*;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.progress.DeferredTreeContentManager;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;

public class MigrationPage extends WizardPage implements ISelectableIUsPage, Listener {

	protected String currentMessage;
	//	protected Button destinationBrowseButton;
	protected CheckboxTreeViewer viewer = null;
	protected Exception finishException;
	protected boolean entryChanged = false;
	protected static IProfileRegistry profileRegistry = null;
	static IProvisioningAgent agent = null;
	protected Button updateToLatest;

	public static final String REMIND_ME_LATER = "remindMeToMigrateLater";

	IProfile profile = null;

	private ProvisioningOperationWizard wizard;
	private ProvisioningUI ui;

	protected IProvisioningAgent otherInstanceAgent = null;
	private Collection<IInstallableUnit> unitsToMigrate;
	private IProfile toImportFrom = null;
	//	private File instancePath = null;
	private URI[] metaURIs = null;
	private URI[] artiURIs = null;

	/**
	 * {@link DelayedFilterCheckboxTree} has a timing bug to prevent restoring the check state,
	 * the methods {@link DeferredTreeContentManager}'s runClearPlaceholderJob and
	 * DelayedFilterCheckboxTree.doCreateRefreshJob().new JobChangeAdapter() {...}.done(IJobChangeEvent) has timing issue,
	 * I can't find a way to guarantee the first job is executed firstly
	 *
	 */
	final class ImportExportFilteredTree extends FilteredTree {
		ArrayList<Object> checkState = new ArrayList<Object>();

		ImportExportFilteredTree(Composite parent, int treeStyle, PatternFilter filter, boolean useNewLook) {
			super(parent, treeStyle, filter, useNewLook);
		}

		@Override
		protected TreeViewer doCreateTreeViewer(Composite composite, int style) {
			return new CheckboxTreeViewer(composite, style);
		}

		@Override
		protected WorkbenchJob doCreateRefreshJob() {
			WorkbenchJob job = super.doCreateRefreshJob();
			job.addJobChangeListener(new JobChangeAdapter() {
				@Override
				public void aboutToRun(IJobChangeEvent event) {
					Display.getDefault().syncExec(new Runnable() {

						public void run() {
							Object[] checked = viewer.getCheckedElements();
							if (checkState == null)
								checkState = new ArrayList<Object>(checked.length);
							for (int i = 0; i < checked.length; i++)
								if (!viewer.getGrayed(checked[i]))
									if (!checkState.contains(checked[i]))
										checkState.add(checked[i]);
						}
					});
				}

				@Override
				public void done(IJobChangeEvent event) {
					if (event.getResult().isOK()) {
						Display.getDefault().asyncExec(new Runnable() {

							public void run() {
								if (viewer == null || viewer.getTree().isDisposed())
									return;
								if (checkState == null)
									return;

								viewer.setCheckedElements(new Object[0]);
								viewer.setGrayedElements(new Object[0]);
								// Now we are only going to set the check state of the leaf nodes
								// and rely on our container checked code to update the parents properly.
								Iterator<Object> iter = checkState.iterator();
								while (iter.hasNext()) {
									viewer.setChecked(iter.next(), true);
								}

								updatePageCompletion();
							}
						});
					}
				}
			});
			return job;
		}
	}

	class TreeViewerComparator extends ViewerComparator {
		private int sortColumn = 0;
		private int lastSortColumn = 0;
		private boolean ascending = false;
		private boolean lastAscending = false;

		@Override
		public int compare(Viewer viewer1, Object e1, Object e2) {
			IInstallableUnit iu1 = ProvUI.getAdapter(e1, IInstallableUnit.class);
			IInstallableUnit iu2 = ProvUI.getAdapter(e2, IInstallableUnit.class);
			if (iu1 != null && iu2 != null) {
				if (viewer1 instanceof TreeViewer) {
					TreeViewer treeViewer = (TreeViewer) viewer1;
					IBaseLabelProvider baseLabel = treeViewer.getLabelProvider();
					if (baseLabel instanceof ITableLabelProvider) {
						ITableLabelProvider tableProvider = (ITableLabelProvider) baseLabel;
						String e1p = tableProvider.getColumnText(e1, getSortColumn());
						String e2p = tableProvider.getColumnText(e2, getSortColumn());
						// don't suppress this warning as it will cause build-time warning
						// see bug 423628. This should be possible to fix once
						// SWT/JFace adopts generics
						int result = getComparator().compare(e1p, e2p);
						// Secondary column sort
						if (result == 0) {
							e1p = tableProvider.getColumnText(e1, lastSortColumn);
							e2p = tableProvider.getColumnText(e2, lastSortColumn);
							// don't suppress this warning as it will cause build-time warning
							// see bug 423628. This should be possible to fix once
							// SWT/JFace adopts generics
							int result2 = getComparator().compare(e1p, e2p);
							return lastAscending ? result2 : (-1) * result2;
						}
						return isAscending() ? result : (-1) * result;
					}
				}
				// we couldn't determine a secondary sort, call it equal
				return 0;
			}
			return super.compare(viewer1, e1, e2);
		}

		/**
		 * @return Returns the sortColumn.
		 */
		public int getSortColumn() {
			return sortColumn;
		}

		/**
		 * @param sortColumn
		 *            The sortColumn to set.
		 */
		public void setSortColumn(int sortColumn) {
			if (this.sortColumn != sortColumn) {
				lastSortColumn = this.sortColumn;
				lastAscending = this.ascending;
				this.sortColumn = sortColumn;
			}
		}

		/**
		 * @return Returns the ascending.
		 */
		public boolean isAscending() {
			return ascending;
		}

		/**
		 * @param ascending
		 *            The ascending to set.
		 */
		public void setAscending(boolean ascending) {
			this.ascending = ascending;
		}
	}

	static {
		BundleContext context = Platform.getBundle(ProvUIActivator.PLUGIN_ID).getBundleContext();
		ServiceTracker<IProvisioningAgent, IProvisioningAgent> tracker = new ServiceTracker<IProvisioningAgent, IProvisioningAgent>(context, IProvisioningAgent.class, null);
		tracker.open();
		agent = tracker.getService();
		tracker.close();
		if (agent != null)
			profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
	}

	public MigrationPage(String pageName) {
		super(pageName);
	}

	public MigrationPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IProfile toImportFrom, Collection<IInstallableUnit> unitsToMigrate, boolean firstTime) {
		super("MigrationPageInstance"); //$NON-NLS-1$
		this.wizard = wizard;
		this.ui = ui;
		profile = getSelfProfile();
		this.toImportFrom = toImportFrom;
		this.unitsToMigrate = unitsToMigrate;
		setTitle(firstTime ? ProvUIMessages.MigrationPage_DIALOG_TITLE_FIRSTRUN : ProvUIMessages.MigrationPage_DIALOG_TITLE);
		setDescription(NLS.bind(ProvUIMessages.MigrationPage_DIALOG_DESCRIPTION, Platform.getProduct().getName()));
	}

	public MigrationPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, boolean firstTime) {
		super("importfrominstancepage"); //$NON-NLS-1$
		this.wizard = wizard;
		this.ui = ui;
		setTitle(firstTime ? ProvUIMessages.MigrationPage_DIALOG_TITLE_FIRSTRUN : ProvUIMessages.MigrationPage_DIALOG_TITLE);
		setDescription(NLS.bind(ProvUIMessages.MigrationPage_DIALOG_DESCRIPTION, Platform.getProduct().getName()));
	}

	protected IProfile getSelfProfile() {
		if (profileRegistry != null) {
			String selfID = System.getProperty("eclipse.p2.profile"); //$NON-NLS-1$
			if (selfID == null)
				selfID = IProfileRegistry.SELF;
			return profileRegistry.getProfile(selfID);
		}
		return null;
	}

	private void createColumns(TreeViewer treeViewer) {
		String[] titles = {ProvUIMessages.Column_Name, ProvUIMessages.Column_Version, ProvUIMessages.Column_Id};
		for (int i = 0; i < titles.length; i++) {
			TreeViewerColumn column = new TreeViewerColumn(treeViewer, SWT.NONE);
			column.getColumn().setText(titles[i]);
			column.getColumn().setResizable(true);
			column.getColumn().setMoveable(true);
			if (titles[i].equals(ProvUIMessages.Column_Name)) {
				column.getColumn().setWidth(300);
			} else {
				column.getColumn().setWidth(200);
			}
			if (ProvUIMessages.Column_Name.equals(titles[i]))
				updateTableSorting(i);
			final int columnIndex = i;
			column.getColumn().addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					updateTableSorting(columnIndex);
				}
			});
		}
	}

	protected void updateTableSorting(int columnIndex) {
		TreeViewerComparator comparator = (TreeViewerComparator) viewer.getComparator();
		// toggle direction if it's the same column
		if (columnIndex == comparator.getSortColumn()) {
			comparator.setAscending(!comparator.isAscending());
		}
		comparator.setSortColumn(columnIndex);
		viewer.getTree().setSortColumn(viewer.getTree().getColumn(columnIndex));
		viewer.getTree().setSortDirection(comparator.isAscending() ? SWT.UP : SWT.DOWN);
		viewer.refresh(false);
	}

	public void createControl(Composite parent) {
		initializeDialogUnits(parent);
		//		initializeService();
		Composite composite = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout(1, true);
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 5;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));

		createContents(composite);

		// can not finish initially, but don't want to start with an error
		// message either
		if (!(validateOptionsGroup())) {
			setPageComplete(false);
		}

		setControl(composite);
		//		giveFocusToDestination();
		Dialog.applyDialogFont(composite);
	}

	protected IUColumnConfig[] getColumnConfig() {
		return new IUColumnConfig[] {new IUColumnConfig(org.eclipse.equinox.internal.p2.ui.ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME, ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH), new IUColumnConfig(org.eclipse.equinox.internal.p2.ui.ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION, ILayoutConstants.DEFAULT_SMALL_COLUMN_WIDTH), new IUColumnConfig(org.eclipse.equinox.internal.p2.ui.ProvUIMessages.ProvUI_IdColumnTitle, IUColumnConfig.COLUMN_ID, ILayoutConstants.DEFAULT_COLUMN_WIDTH)};
	}

	protected void createContents(Composite composite) {
		createInstallationTable(composite);
		createAdditionOptions(composite);
	}

	protected void createInstallationTable(final Composite parent) {

		SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
		FillLayout fill = new FillLayout();
		sashForm.setLayout(fill);
		GridData data = new GridData(GridData.FILL_BOTH);
		sashForm.setLayoutData(data);
		Composite sashComposite = new Composite(sashForm, SWT.NONE);
		GridLayout grid = new GridLayout();
		grid.marginWidth = 0;
		grid.marginHeight = 0;
		sashComposite.setLayout(grid);

		PatternFilter filter = getPatternFilter();
		filter.setIncludeLeadingWildcard(true);
		final ImportExportFilteredTree filteredTree = new ImportExportFilteredTree(sashComposite, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, filter, true);
		viewer = (CheckboxTreeViewer) filteredTree.getViewer();
		final Tree tree = viewer.getTree();
		tree.setHeaderVisible(true);
		tree.setLinesVisible(false);
		GridData treeDataGrid = new GridData(GridData.FILL_BOTH);
		treeDataGrid.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT);
		treeDataGrid.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH);
		tree.setLayoutData(treeDataGrid);

		viewer.setComparator(new TreeViewerComparator());
		viewer.setComparer(new ProvElementComparer());
		createColumns(viewer);
		final ITreeContentProvider contentProvider = getContentProvider();
		viewer.setContentProvider(contentProvider);
		viewer.setLabelProvider(getLabelProvider());
		viewer.addCheckStateListener(new ICheckStateListener() {

			public void checkStateChanged(CheckStateChangedEvent event) {
				if (!event.getChecked() && filteredTree.checkState != null) {
					ArrayList<Object> toRemove = new ArrayList<Object>(1);
					// See bug 258117.  Ideally we would get check state changes
					// for children when the parent state changed, but we aren't, so
					// we need to remove all children from the additive check state
					// cache.
					if (contentProvider.hasChildren(event.getElement())) {
						Set<Object> unchecked = new HashSet<Object>();
						Object[] children = contentProvider.getChildren(event.getElement());
						for (int i = 0; i < children.length; i++) {
							unchecked.add(children[i]);
						}
						Iterator<Object> iter = filteredTree.checkState.iterator();
						while (iter.hasNext()) {
							Object current = iter.next();
							if (current != null && unchecked.contains(current)) {
								toRemove.add(current);
							}
						}
					} else {
						for (Object element : filteredTree.checkState) {
							if (viewer.getComparer().equals(element, event.getElement())) {
								toRemove.add(element);
								// Do not break out of the loop.  We may have duplicate equal
								// elements in the cache.  Since the cache is additive, we want
								// to be sure we've gotten everything.
							}
						}
					}
					filteredTree.checkState.removeAll(toRemove);
				}
			}
		});
		parent.addControlListener(new ControlAdapter() {
			private final int[] columnRate = new int[] {6, 2, 2};

			@Override
			public void controlResized(ControlEvent e) {
				Rectangle area = parent.getClientArea();
				Point size = tree.computeSize(SWT.DEFAULT, SWT.DEFAULT);
				ScrollBar vBar = tree.getVerticalBar();
				int width = area.width - tree.computeTrim(0, 0, 0, 0).width - vBar.getSize().x;
				if (size.y > area.height + tree.getHeaderHeight()) {
					// Subtract the scrollbar width from the total column width
					// if a vertical scrollbar will be required
					Point vBarSize = vBar.getSize();
					width -= vBarSize.x;
				}
				Point oldSize = tree.getSize();
				TreeColumn[] columns = tree.getColumns();
				int hasUsed = 0, i = 0;
				if (oldSize.x > area.width) {
					// table is getting smaller so make the columns
					// smaller first and then resize the table to
					// match the client area width
					for (; i < columns.length - 1; i++) {
						columns[i].setWidth(width * columnRate[i] / 10);
						hasUsed += columns[i].getWidth();
					}
					columns[columns.length - 1].setWidth(width - hasUsed);
					tree.setSize(area.width, area.height);
				} else {
					// table is getting bigger so make the table
					// bigger first and then make the columns wider
					// to match the client area width
					tree.setSize(area.width, area.height);
					for (; i < columns.length - 1; i++) {
						columns[i].setWidth(width * columnRate[i] / 10);
						hasUsed += columns[i].getWidth();
					}
					columns[columns.length - 1].setWidth(width - hasUsed);
				}
			}
		});
		ICheckStateProvider provider = getViewerDefaultState();
		if (provider != null)
			viewer.setCheckStateProvider(provider);
		else
			viewer.addSelectionChangedListener(new ISelectionChangedListener() {
				public void selectionChanged(SelectionChangedEvent event) {
					updatePageCompletion();
				}
			});
		viewer.getControl().setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
		viewer.setInput(getInput());

		viewer.getTree().addListener(SWT.Selection, new Listener() {

			public void handleEvent(Event event) {
				if (event.detail == SWT.CHECK) {
					if (hasInstalled(ProvUI.getAdapter(event.item.getData(), IInstallableUnit.class))) {
						viewer.getTree().setRedraw(false);
						((TreeItem) event.item).setChecked(false);
						viewer.getTree().setRedraw(true);
					}
				}
				updatePageCompletion();
			}
		});

		Composite buttons = new Composite(sashComposite, SWT.NONE);
		buttons.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
		buttons.setLayout(new RowLayout(SWT.HORIZONTAL));
		Button selectAll = new Button(buttons, SWT.PUSH);
		selectAll.setText(ProvUIMessages.AbstractPage_ButtonSelectAll);
		selectAll.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				for (TreeItem item : viewer.getTree().getItems()) {
					if (!item.getChecked()) {
						item.setChecked(true);
						Event event = new Event();
						event.widget = item.getParent();
						event.detail = SWT.CHECK;
						event.item = item;
						event.type = SWT.Selection;
						viewer.getTree().notifyListeners(SWT.Selection, event);
					}
				}
				updatePageCompletion();
			}
		});
		Button deselectAll = new Button(buttons, SWT.PUSH);
		deselectAll.setText(ProvUIMessages.AbstractPage_ButtonDeselectAll);
		deselectAll.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				for (TreeItem item : viewer.getTree().getItems()) {
					viewer.setSubtreeChecked(item.getData(), false);
				}
				updatePageCompletion();
			}
		});

	}

	protected void createAdditionOptions(Composite parent) {

		Composite composite = new Composite(parent, SWT.BORDER);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));

		updateToLatest = new Button(composite, SWT.CHECK);
		updateToLatest.setText(ProvUIMessages.MigrationPage_UPDATE_TO_LATEST);
		updateToLatest.setSelection(loadCustomizedSetting());

	}

	protected PatternFilter getPatternFilter() {
		return new AvailableIUPatternFilter(getColumnConfig());
	}

	protected ICheckStateProvider getViewerDefaultState() {
		return new ICheckStateProvider() {

			public boolean isGrayed(Object element) {
				return false;
			}

			public boolean isChecked(Object element) {
				if (profile != null) {
					IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
					IQueryResult<IInstallableUnit> collector = profile.query(QueryUtil.createIUQuery(iu.getId(), new VersionRange(iu.getVersion(), true, null, false)), new NullProgressMonitor());
					if (collector.isEmpty()) {
						return true;
					}
				}
				return false;
			}
		};
	}

	//	protected ITableLabelProvider getLabelProvider() {
	//		return new IUDetailsLabelProvider(null, getColumnConfig(), null);
	//	}

	protected ITreeContentProvider getContentProvider() {
		ProvElementContentProvider provider = new ProvElementContentProvider() {
			@Override
			public boolean hasChildren(Object element) {
				if (element instanceof InstalledIUElement)
					return false;
				return super.hasChildren(element);
			}

			@Override
			public Object[] getChildren(Object parent) {
				if (parent instanceof InstalledIUElement)
					return new Object[0];
				return super.getChildren(parent);
			}
		};
		return provider;
	}

	protected boolean determinePageCompletion() {
		currentMessage = null;
		// validate groups in order of priority so error message is the most important one
		boolean complete = validateOptionsGroup();

		// Avoid draw flicker by not clearing the error
		// message unless all is valid.
		if (complete) {
			setErrorMessage(null);
		} else {
			setErrorMessage(currentMessage);
		}

		return complete;
	}

	protected int getBrowseDialogStyle() {
		return SWT.OPEN;
	}

	//TODO remove the implementation of Listener
	public void handleEvent(Event event) {
		//		Widget source = event.widget;
		//
		//		if (source == destinationBrowseButton) {
		//			handleDestinationBrowseButtonPressed();
		//		}
		//		updatePageCompletion();
	}

	/**
	 * Determine if the page is complete and update the page appropriately.
	 */
	protected void updatePageCompletion() {
		boolean pageComplete = determinePageCompletion();
		setPageComplete(pageComplete);
		if (pageComplete) {
			//			if (this instanceof AbstractImportPage_c)
			//				saveWidgetValues();
			setMessage(null);
		}
	}

	protected boolean validateOptionsGroup() {
		if (viewer == null || viewer.getCheckedElements().length > 0)
			return true;

		currentMessage = getNoOptionsMessage();
		return false;
	}

	protected ProvisioningOperationWizard getProvisioningWizard() {
		return wizard;
	}

	protected ProvisioningUI getProvisioningUI() {
		return ui;
	}

	public boolean hasInstalled(IInstallableUnit iu) {
		IQueryResult<IInstallableUnit> results = profile.query(QueryUtil.createIUQuery(iu.getId(), new VersionRange(iu.getVersion(), true, null, false)), null);
		return !results.isEmpty();
	}

	public String getIUNameWithDetail(IInstallableUnit iu) {
		IQueryResult<IInstallableUnit> results = profile.query(QueryUtil.createIUQuery(iu.getId(), new VersionRange(iu.getVersion(), true, null, false)), null);
		String text = iu.getProperty(IProfile.PROP_NAME, null);
		text = (text != null) ? text : iu.getId();
		if (!results.isEmpty()) {
			boolean hasHigherVersion = false;
			boolean hasEqualVersion = false;
			for (IInstallableUnit installedIU : results.toSet()) {
				int compareValue = installedIU.getVersion().compareTo(iu.getVersion());
				if (compareValue > 0) {
					hasHigherVersion = true;
					break;
				} else if (compareValue == 0)
					hasEqualVersion = true;
			}
			if (hasHigherVersion)
				return NLS.bind(ProvUIMessages.AbstractImportPage_HigherVersionInstalled, text);
			else if (hasEqualVersion)
				return NLS.bind(ProvUIMessages.AbstractImportPage_SameVersionInstalled, text);
		}
		return text;
	}

	protected void doFinish() throws Exception {
		// do nothing
	}

	@Override
	public boolean canFlipToNextPage() {
		return isPageComplete();
	}

	protected String getDialogTitle() {
		return ProvUIMessages.MigrationPage_DIALOG_TITLE;
	}

	protected Object getInput() {

		IUElementListRoot root = new IUElementListRoot();
		List<AvailableIUElement> elements = new ArrayList<AvailableIUElement>(unitsToMigrate.size());
		for (IInstallableUnit unit : unitsToMigrate) {
			elements.add(new AvailableIUElement(root, unit, toImportFrom.getProfileId(), false));
		}
		root.setChildren(elements.toArray());
		return root;
	}

	protected String getInvalidDestinationMessage() {
		return "";//ProvUIMessages.ImportFromInstallationPage_INVALID_DESTINATION; //$NON-NLS-1$
	}

	protected String getNoOptionsMessage() {
		return ProvUIMessages.MigrationPage_SELECT_COMPONENT;
	}

	class ImportFromInstallationLabelProvider extends IUDetailsLabelProvider {
		@Override
		public String getColumnText(Object element, int columnIndex) {
			String text = super.getColumnText(element, columnIndex);
			// it's the order of label provider
			if (columnIndex == 0) {
				IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
				return getIUNameWithDetail(iu);
			}
			return text;
		}

		@Override
		public Color getForeground(Object element) {
			IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
			if (hasInstalled(iu))
				return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
			return super.getForeground(element);
		}
	}

	protected ITableLabelProvider getLabelProvider() {
		return new ImportFromInstallationLabelProvider();
	}

	@Override
	public void dispose() {
		super.dispose();
		if (otherInstanceAgent != null) {
			otherInstanceAgent.stop();
			otherInstanceAgent = null;
			toImportFrom = null;
		}
		cleanLocalRepository();
	}

	public void cleanLocalRepository() {
		if (metaURIs != null && metaURIs.length > 0) {
			IProvisioningAgent runningAgent = getProvisioningUI().getSession().getProvisioningAgent();
			IMetadataRepositoryManager manager = (IMetadataRepositoryManager) runningAgent.getService(IMetadataRepositoryManager.SERVICE_NAME);
			for (URI uri : metaURIs)
				manager.removeRepository(uri);
			IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) runningAgent.getService(IArtifactRepositoryManager.SERVICE_NAME);
			for (URI uri : artiURIs)
				artifactManager.removeRepository(uri);
		}
	}

	// Both checkedElements and checkedElementsUpdates and the logic inside the getCheckedIUElements method
	// are used to prevent unnecessary call to getUpdates method due to computational cost.
	@SuppressWarnings("rawtypes")
	private Set checkedElements;
	@SuppressWarnings("rawtypes")
	private Set checkedElementsUpdates;
	private boolean getUpdatesCanceled;

	public Object[] getCheckedIUElements() {

		if (isUpdateToLatest()) {

			Object[] latestUpdates = getLatestVersionOfCheckedElements();

			// If the getUpdades operation is cancelled, then set checkedElements and checkedElementsUpdates to null to force the lookup for updates again. Thereafter throw OperationCanceledException.
			if (getUpdatesCanceled) {

				this.checkedElements = null;
				this.checkedElementsUpdates = null;
				throw new OperationCanceledException();
			}
			return latestUpdates;
		}
		return viewer.getCheckedElements();
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	private Object[] getLatestVersionOfCheckedElements() {

		Object[] checkedArray = viewer.getCheckedElements();
		if (this.checkedElements == null) {
			// initialize checkedElements and checkedElementsUpdates for the first time
			this.checkedElements = new HashSet(Arrays.asList(checkedArray));
			this.checkedElementsUpdates = new HashSet(Arrays.asList(getUpdates(checkedArray)));

		} else {
			Set checkedElementsNow = new HashSet(Arrays.asList(checkedArray));
			if (checkedElementsNow.size() != this.checkedElements.size() || (!checkedElementsNow.containsAll(checkedElements))) {
				// only if the set of checkedElements has changed get the update for them
				this.checkedElements = checkedElementsNow; //
				this.checkedElementsUpdates = new HashSet(Arrays.asList(getUpdates(checkedArray)));
			}
		}

		return this.checkedElementsUpdates.toArray();
	}

	public Object[] getSelectedIUElements() {
		// TODO Auto-generated method stub
		return null;
	}

	public void setCheckedElements(Object[] elements) {
		new UnsupportedOperationException();
	}

	// Look for update of the current selected installation units and replace the old ons with the updated version
	private Object[] getUpdates(final Object[] _checkedElements) {

		final Collection<IInstallableUnit> toInstall = new ArrayList<IInstallableUnit>();

		try {
			getContainer().run(false, true, new IRunnableWithProgress() {

				public void run(IProgressMonitor monitor) {
					SubMonitor sub = SubMonitor.convert(monitor, _checkedElements.length);
					ProvisioningContext context = new ProvisioningContext(getProvisioningUI().getSession().getProvisioningAgent());

					for (Object iu : _checkedElements) {

						if (sub.isCanceled()) {
							MigrationPage.this.getUpdatesCanceled = true;
							toInstall.clear();
							sub.done();
							return;
						}

						if (iu instanceof AvailableIUElement) {
							IInstallableUnit unit = ((AvailableIUElement) iu).getIU();
							IuUpdateAndPatches updateAndPatches = filterToInstall(unit, updatesFor(unit, context, sub.newChild(1)));
							if (updateAndPatches.update != null) {
								toInstall.add(updateAndPatches.update);
							} else {
								toInstall.add(updateAndPatches.iu); // because it is not yet installed
								toInstall.addAll(updateAndPatches.patches);
							}

						}

						sub.worked(1);
					}
				}

			});
		} catch (InterruptedException e) {
			// Nothing to report if thread was interrupted
		} catch (InvocationTargetException e) {
			ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG);
		}

		return toInstall.toArray();

	}

	public boolean isUpdateToLatest() {
		return updateToLatest.getSelection();
	}

	public ProvisioningContext getProvisioningContext() {
		ProvisioningContext context = new ProvisioningContext(getProvisioningUI().getSession().getProvisioningAgent());
		context.setArtifactRepositories(artiURIs);
		context.setMetadataRepositories(metaURIs);
		return context;
	}

	private static boolean hasHigherFidelity(IInstallableUnit iu, IInstallableUnit currentIU) {
		if (Boolean.valueOf(currentIU.getProperty(IInstallableUnit.PROP_PARTIAL_IU)).booleanValue() && !Boolean.valueOf(iu.getProperty(IInstallableUnit.PROP_PARTIAL_IU)).booleanValue())
			return true;
		return false;
	}

	public Collection<IInstallableUnit> updatesFor(IInstallableUnit toUpdate, ProvisioningContext context, IProgressMonitor monitor) {
		//		IPlanner planner = (IPlanner) getProvisioningUI().getSession().getProvisioningAgent().getService(IPlanner.SERVICE_NAME);
		//		return planner.updatesFor(toUpdate, context, monitor).toSet();

		Map<String, IInstallableUnit> resultsMap = new HashMap<String, IInstallableUnit>();

		SubMonitor sub = SubMonitor.convert(monitor, 1000);
		IQueryable<IInstallableUnit> queryable = context.getMetadata(sub.newChild(500));
		IQueryResult<IInstallableUnit> matches = queryable.query(new UpdateQuery(toUpdate), sub.newChild(500));
		for (Iterator<IInstallableUnit> it = matches.iterator(); it.hasNext();) {
			IInstallableUnit iu = it.next();
			String key = iu.getId() + "_" + iu.getVersion().toString(); //$NON-NLS-1$
			IInstallableUnit currentIU = resultsMap.get(key);
			if (currentIU == null || hasHigherFidelity(iu, currentIU))
				resultsMap.put(key, iu);
		}
		sub.done();
		return resultsMap.values();
	}

	class IuUpdateAndPatches {
		public IInstallableUnit iu;
		public IInstallableUnit update;
		public Collection<IInstallableUnit> patches;

		IuUpdateAndPatches(IInstallableUnit iu) {
			this.iu = iu;
			this.patches = new ArrayList<IInstallableUnit>();
		}

	}

	/**
	 *
	 * @param iu original unit.
	 * @param updates list of updates: patches or true updates.
	 * @return a structure holding the original unit, its most recent update and any available patches.
	 */
	private IuUpdateAndPatches filterToInstall(IInstallableUnit iu, Collection<IInstallableUnit> updates) {

		IuUpdateAndPatches updateAndPatches = new IuUpdateAndPatches(iu);

		for (IInstallableUnit update : updates) {

			if (QueryUtil.isPatch(update)) {
				updateAndPatches.patches.add(update);
			} else {
				if (updateAndPatches.update == null || updateAndPatches.update.getVersion().compareTo(update.getVersion()) < 0) {
					updateAndPatches.update = update;
				}
			}
		}

		return updateAndPatches;
	}

	public static boolean loadCustomizedSetting() {
		IScopeContext[] contexts = new IScopeContext[] {InstanceScope.INSTANCE, DefaultScope.INSTANCE, BundleDefaultsScope.INSTANCE, ConfigurationScope.INSTANCE};
		boolean updateToLatest = Platform.getPreferencesService().getBoolean(AutomaticUpdatePlugin.PLUGIN_ID, "updateToLatest", false, contexts);
		return updateToLatest;
	}

}