/*******************************************************************************
 * Copyright (c) 2006, 2017 IBM 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:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ui.mapping;

import java.util.*;
import java.util.List;

import org.eclipse.core.resources.mapping.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.core.diff.*;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.core.mapping.ISynchronizationScope;
import org.eclipse.team.internal.core.subscribers.SubscriberDiffTreeEventHandler;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.internal.ui.synchronize.*;
import org.eclipse.team.ui.ISharedImages;
import org.eclipse.team.ui.TeamUI;
import org.eclipse.team.ui.mapping.*;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Hyperlink;

public class DiffTreeChangesSection extends ForwardingChangesSection implements IDiffChangeListener, IPropertyChangeListener, IEmptyTreeListener {

	private ISynchronizationContext context;
	private IStatus[] errors;
	private boolean showingError;
	private JobChangeAdapter jobChangeListener;

	public interface ITraversalFactory {
		ResourceTraversal[] getTraversals(ISynchronizationScope scope);
	}

	public DiffTreeChangesSection(Composite parent, AbstractSynchronizePage page, ISynchronizePageConfiguration configuration) {
		super(parent, page, configuration);
		context = (ISynchronizationContext)configuration.getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT);
		context.getDiffTree().addDiffChangeListener(this);
		getConfiguration().addPropertyChangeListener(this);
		jobChangeListener = new JobChangeAdapter() {
			@Override
			public void running(IJobChangeEvent event) {
				if (isJobOfInterest(event.getJob())) {
					if (context.getDiffTree().isEmpty())
						calculateDescription();
				}
			}
			private boolean isJobOfInterest(Job job) {
				if (job.belongsTo(getConfiguration().getParticipant()))
					return true;
				SubscriberDiffTreeEventHandler handler = getHandler();
				if (handler != null && handler.getEventHandlerJob() == job)
					return true;
				return false;
			}
			@Override
			public void done(IJobChangeEvent event) {
				if (isJobOfInterest(event.getJob())) {
					if (context.getDiffTree().isEmpty())
						calculateDescription();
				}
			}
		};
		Job.getJobManager().addJobChangeListener(jobChangeListener);
	}

	@Override
	public void dispose() {
		context.getDiffTree().removeDiffChangeListener(this);
		getConfiguration().removePropertyChangeListener(this);
		Job.getJobManager().removeJobChangeListener(jobChangeListener);
		super.dispose();
	}

	@Override
	protected int getChangesCount() {
		return context.getDiffTree().size();
	}

	@Override
	protected long getChangesInMode(int candidateMode) {
		long numChanges;
		long numConflicts = context.getDiffTree().countFor(IThreeWayDiff.CONFLICTING, IThreeWayDiff.DIRECTION_MASK);
		switch (candidateMode) {
		case ISynchronizePageConfiguration.CONFLICTING_MODE:
			numChanges = numConflicts;
			break;
		case ISynchronizePageConfiguration.OUTGOING_MODE:
			numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK);
			break;
		case ISynchronizePageConfiguration.INCOMING_MODE:
			numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK);
			break;
		case ISynchronizePageConfiguration.BOTH_MODE:
			numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK)
				+ context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK);
			break;
		default:
			numChanges = 0;
			break;
		}
		return numChanges;
	}

	protected boolean hasChangesInMode(String id, ISynchronizationCompareAdapter adapter, int candidateMode) {
		switch (candidateMode) {
		case ISynchronizePageConfiguration.CONFLICTING_MODE:
			return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING }, IThreeWayDiff.DIRECTION_MASK);
		case ISynchronizePageConfiguration.OUTGOING_MODE:
			return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.OUTGOING }, IThreeWayDiff.DIRECTION_MASK);
		case ISynchronizePageConfiguration.INCOMING_MODE:
			return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.INCOMING }, IThreeWayDiff.DIRECTION_MASK);
		case ISynchronizePageConfiguration.BOTH_MODE:
			return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.INCOMING, IThreeWayDiff.OUTGOING }, IThreeWayDiff.DIRECTION_MASK);
		}
		return false;
	}

	private boolean hasChangesFor(String id, ISynchronizationCompareAdapter adapter, ISynchronizationContext context, int[] states, int mask) {
		ITraversalFactory factory = Adapters.adapt(adapter, ITraversalFactory.class);
		ResourceTraversal[] traversals;
		if (factory == null) {
			traversals = context.getScope().getTraversals(id);
		} else {
			traversals = factory.getTraversals(context.getScope());
		}
		return (context.getDiffTree().hasMatchingDiffs(traversals, FastDiffFilter.getStateFilter(states, mask)));
	}

	@Override
	protected long getVisibleChangesCount() {
		ISynchronizePageConfiguration configuration = getConfiguration();
		if (configuration.getComparisonType() == ISynchronizePageConfiguration.TWO_WAY) {
			return context.getDiffTree().size();
		}
		int currentMode =  configuration.getMode();
		String id = (String)configuration.getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER);
		if (id != null && !id.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) {
			try {
				IModelProviderDescriptor desc = ModelProvider.getModelProviderDescriptor(id);
				ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(desc.getModelProvider());
				if (adapter != null) {
					return hasChangesInMode(desc.getId(), adapter, getConfiguration().getMode()) ? -1 : 0;
				}
			} catch (CoreException e) {
				TeamUIPlugin.log(e);
			}
			// Use the view state to indicate whether there are visible changes
			return isViewerEmpty() ? 0 : -1;
		}
		return getChangesInMode(currentMode);
	}

	@Override
	protected int getCandidateMode() {
		SynchronizePageConfiguration configuration = (SynchronizePageConfiguration)getConfiguration();
		long outgoingChanges = context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK);
		if (outgoingChanges > 0) {
			if (configuration.isModeSupported(ISynchronizePageConfiguration.OUTGOING_MODE)) {
				return ISynchronizePageConfiguration.OUTGOING_MODE;
			}
			if (configuration.isModeSupported(ISynchronizePageConfiguration.BOTH_MODE)) {
				return ISynchronizePageConfiguration.BOTH_MODE;
			}
		}
		long incomingChanges = context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK);
		if (incomingChanges > 0) {
			if (configuration.isModeSupported(ISynchronizePageConfiguration.INCOMING_MODE)) {
				return ISynchronizePageConfiguration.INCOMING_MODE;
			}
			if (configuration.isModeSupported(ISynchronizePageConfiguration.BOTH_MODE)) {
				return ISynchronizePageConfiguration.BOTH_MODE;
			}
		}
		return configuration.getMode();
	}

	@Override
	public void diffsChanged(IDiffChangeEvent event, IProgressMonitor monitor) {
		IStatus[] errors = event.getErrors();
		if (errors.length > 0) {
			this.errors = errors;
		}
		calculateDescription();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.diff.IDiffChangeListener#propertyChanged(int, org.eclipse.core.runtime.IPath[])
	 */
	@Override
	public void propertyChanged(IDiffTree tree, int property, IPath[] paths) {
		// Do nothing
	}

	@Override
	public void propertyChange(PropertyChangeEvent event) {
		if (event.getProperty().equals(ISynchronizePageConfiguration.P_MODE)
				|| event.getProperty().equals(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER)) {
			calculateDescription();
		}
	}

	@Override
	protected Composite getEmptyChangesComposite(Composite parent) {
		if (context.getDiffTree().isEmpty()) {
			SubscriberDiffTreeEventHandler handler = getHandler();
			if (handler != null && handler.getState() == SubscriberDiffTreeEventHandler.STATE_STARTED) {
				// The context has not been initialized yet
				return getInitializationPane(parent);
			}
			if (isRefreshRunning() || (handler != null && handler.getEventHandlerJob().getState() != Job.NONE)) {
				return getInitializingMessagePane(parent);
			}
		} else {
			ISynchronizePageConfiguration configuration = getConfiguration();
			String id = (String)configuration.getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER);
			if (id == null)
				id = ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER;
			if (id.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) {
				if (getChangesInMode(getConfiguration().getMode()) > 0 && isAtLeastOneProviderDisabled()) {
					// There are changes in this mode but they are not visible so enable
					// all providers
					return createEnableParticipantModelProvidersPane(parent);
				}
			} else {
				// A particular model is active so we need to look for a model that has changes in this
				// same mode before offering to change modes.
				ModelProvider[] providers =findModelsWithChangesInMode(getConfiguration().getMode());
				ModelProvider currentProvider = null;
				for (int i = 0; i < providers.length; i++) {
					ModelProvider provider = providers[i];
					if (isEnabled(provider)) {
						if (provider.getDescriptor().getId().equals(id)) {
							currentProvider = provider;
						} else {
							return getPointerToModel(parent, provider, id);
						}
					}
				}
				if (currentProvider != null || providers.length > 0) {
					// The current provider has changes but the view is empty
					// or there is a disabled provider with changes
					// This is an error so offer to enable and show all models
					return createEnableParticipantModelProvidersPane(parent);
				}
			}
		}
		return super.getEmptyChangesComposite(parent);
	}

	private boolean isAtLeastOneProviderDisabled() {
		ModelProvider[] providers =findModelsWithChangesInMode(getConfiguration().getMode());
		for (int i = 0; i < providers.length; i++) {
			ModelProvider provider = providers[i];
			if (!isEnabled(provider)) {
				return true;
			}
		}
		return false;
	}

	private ModelProvider[] findModelsWithChangesInMode(int mode) {
		ModelProvider[] providers =context.getScope().getModelProviders();
		providers = ModelOperation.sortByExtension(providers);
		List<ModelProvider> result = new ArrayList<>();
		for (int i = 0; i < providers.length; i++) {
			ModelProvider provider = providers[i];
			ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(provider);
			if (adapter != null) {
				boolean hasChanges = hasChangesInMode(provider.getId(), adapter, getConfiguration().getMode());
				if (hasChanges) {
					result.add(provider);
				}
			}
		}
		return result.toArray(new ModelProvider[result.size()]);
	}

	private boolean isEnabled(ModelProvider provider) {
		ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager().getDescriptor(provider.getId());
		return (desc != null && desc.isEnabled());
	}

	private Composite createEnableParticipantModelProvidersPane(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getListBackgroundColor());
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.grabExcessVerticalSpace = true;
		composite.setLayoutData(data);

		String message;
		int changesCount = getChangesCount();
		if (changesCount == 1) {
			message = TeamUIMessages.DiffTreeChangesSection_8;
		} else {
			message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_9, Integer.valueOf(changesCount));
		}
		final ITeamContentProviderDescriptor[] descriptors = getEnabledContentDescriptors();
		if (descriptors.length == 0)
			message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_10, message);
		else
			message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_11, message);

		createDescriptionLabel(composite, message);

		Label warning = new Label(composite, SWT.NONE);
		warning.setImage(TeamUIPlugin.getPlugin().getImage(ISharedImages.IMG_WARNING_OVR));

		Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_12, SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				ModelSynchronizeParticipant participant = (ModelSynchronizeParticipant)getConfiguration().getParticipant();
				ModelProvider[] providers = participant.getEnabledModelProviders();
				Set<ITeamContentProviderDescriptor> toEnable = new HashSet<>();
				toEnable.addAll(Arrays.asList(descriptors));
				for (int i = 0; i < providers.length; i++) {
					ModelProvider provider = providers[i];
					ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager().getDescriptor(provider.getId());
					if (desc != null && !desc.isEnabled()) {
						toEnable.add(desc);
					}
				}
				TeamUI.getTeamContentProviderManager()
						.setEnabledDescriptors(toEnable.toArray(new ITeamContentProviderDescriptor[toEnable.size()]));
				getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE );

			}
		});
		getForms().getHyperlinkGroup().add(link);

		return composite;
	}

	private ITeamContentProviderDescriptor[] getEnabledContentDescriptors() {
		ModelSynchronizeParticipant participant = (ModelSynchronizeParticipant)getConfiguration().getParticipant();
		ModelProvider[] providers = participant.getEnabledModelProviders();
		Set<ITeamContentProviderDescriptor> result = new HashSet<>();
		for (int i = 0; i < providers.length; i++) {
			ModelProvider provider = providers[i];
			ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager().getDescriptor(provider.getId());
			if (desc != null && desc.isEnabled())
				result.add(desc);
		}
		return result.toArray(new ITeamContentProviderDescriptor[result.size()]);
	}

	private Composite getInitializationPane(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getListBackgroundColor());
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.grabExcessVerticalSpace = true;
		composite.setLayoutData(data);

		createDescriptionLabel(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_3, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) }));

		final boolean[] remember = new boolean[] { false };
		final PreferenceStore store = (PreferenceStore) getConfiguration()
			.getProperty(StartupPreferencePage.STARTUP_PREFERENCES);
		Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_4, SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				if (remember[0] && store != null) {
					store.putValue(StartupPreferencePage.PROP_STARTUP_ACTION, StartupPreferencePage.STARTUP_ACTION_POPULATE);
				}
				getHandler().initializeIfNeeded();
			}
		});
		getForms().getHyperlinkGroup().add(link);

		link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_5, SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				if (remember[0] && store != null) {
					store.putValue(StartupPreferencePage.PROP_STARTUP_ACTION, StartupPreferencePage.STARTUP_ACTION_SYNCHRONIZE);
				}
				getConfiguration().getParticipant().run(getConfiguration().getSite().getPart());
			}
		});
		getForms().getHyperlinkGroup().add(link);

		if (store != null) {
			final Button rememberButton = getForms().createButton(composite, TeamUIMessages.DiffTreeChangesSection_14, SWT.CHECK);
			rememberButton.setToolTipText(TeamUIMessages.DiffTreeChangesSection_14);
			data = new GridData(GridData.FILL_HORIZONTAL);
			data.horizontalSpan = 2;
			data.horizontalIndent=5;
			data.verticalIndent=5;
			data.widthHint = 100;
			rememberButton.setLayoutData(data);
			rememberButton.addSelectionListener(new SelectionListener() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					remember[0] = rememberButton.getSelection();
				}
				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					// Do nothing
				}
			});
		}

		return composite;
	}

	private Composite getInitializingMessagePane(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getListBackgroundColor());
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.grabExcessVerticalSpace = true;
		composite.setLayoutData(data);
		if (isRefreshRunning()) {
			createDescriptionLabel(composite,NLS.bind(TeamUIMessages.DiffTreeChangesSection_6, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) }));
		} else {
			createDescriptionLabel(composite,NLS.bind(TeamUIMessages.DiffTreeChangesSection_7, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) }));
		}
		return composite;
	}

	private boolean isRefreshRunning() {
		return Job.getJobManager().find(getConfiguration().getParticipant()).length > 0;
	}

	private SubscriberDiffTreeEventHandler getHandler() {
		return Adapters.adapt(context, SubscriberDiffTreeEventHandler.class);
	}

	private Composite getPointerToModel(Composite parent, final ModelProvider provider, String oldId) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getListBackgroundColor());
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.grabExcessVerticalSpace = true;
		composite.setLayoutData(data);

		IModelProviderDescriptor oldDesc = ModelProvider.getModelProviderDescriptor(oldId);
		String message;
		String modeToString = Utils.modeToString(getConfiguration().getMode());
        message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_0, new String[] {
            		provider.getDescriptor().getLabel(),
            		modeToString });
		message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_1, new String[] { modeToString, oldDesc.getLabel(), message });

		createDescriptionLabel(composite, message);

		Label warning = new Label(composite, SWT.NONE);
		warning.setImage(TeamUIPlugin.getPlugin().getImage(ISharedImages.IMG_WARNING_OVR));

		Hyperlink link = getForms().createHyperlink(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_2, new String[] { provider.getDescriptor().getLabel() }), SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, provider.getDescriptor().getId() );
			}
		});
		getForms().getHyperlinkGroup().add(link);

		new Label(composite, SWT.NONE);
		Hyperlink link2 = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_13, SWT.WRAP);
		link2.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE );
			}
		});
		getForms().getHyperlinkGroup().add(link2);

		return composite;
	}

	@Override
	public void treeEmpty(TreeViewer viewer) {
		handleEmptyViewer();
	}

	private void handleEmptyViewer() {
		// Override stand behavior to do our best to show something
		TeamUIPlugin.getStandardDisplay().asyncExec(() -> {
			if (!getContainer().isDisposed())
				updatePage(getEmptyChangesComposite(getContainer()));
		});
	}

	@Override
	protected void calculateDescription() {
		if (errors != null && errors.length > 0) {
			if (!showingError) {
				TeamUIPlugin.getStandardDisplay().asyncExec(() -> {
					updatePage(getErrorComposite(getContainer()));
					showingError = true;
				});
			}
			return;
		}
		showingError = false;
		if (isViewerEmpty()) {
			handleEmptyViewer();
		} else {
			super.calculateDescription();
		}
	}

	private boolean isViewerEmpty() {
		Viewer v = getPage().getViewer();
		if (v instanceof CommonViewerAdvisor.NavigableCommonViewer) {
			CommonViewerAdvisor.NavigableCommonViewer cv = (CommonViewerAdvisor.NavigableCommonViewer) v;
			return cv.isEmpty();
		}
		return false;
	}

	@Override
	public void notEmpty(TreeViewer viewer) {
		calculateDescription();
	}

	private Composite getErrorComposite(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getListBackgroundColor());
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.grabExcessVerticalSpace = true;
		composite.setLayoutData(data);

		createDescriptionLabel(composite, NLS.bind(TeamUIMessages.ChangesSection_10, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) }));

		Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.ChangesSection_8, SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				showErrors();
			}
		});
		getForms().getHyperlinkGroup().add(link);

		link = getForms().createHyperlink(composite, TeamUIMessages.ChangesSection_9, SWT.WRAP);
		link.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				errors = null;
				calculateDescription();
				SubscriberDiffTreeEventHandler handler = getHandler();
				if (handler != null)
					handler.initializeIfNeeded();
				else
					getConfiguration().getParticipant().run(getConfiguration().getSite().getPart());
			}
		});
		getForms().getHyperlinkGroup().add(link);

		return composite;
	}

	/* private */ void showErrors() {
		if (errors != null) {
			IStatus[] status = errors;
			String title = TeamUIMessages.ChangesSection_11;
			if (status.length == 1) {
				ErrorDialog.openError(getShell(), title, status[0].getMessage(), status[0]);
			} else {
				MultiStatus multi = new MultiStatus(TeamUIPlugin.ID, 0, status, TeamUIMessages.ChangesSection_12, null);
				ErrorDialog.openError(getShell(), title, null, multi);
			}
		}
	}
}
