/*******************************************************************************
 * Copyright (c) 2009, 2011 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
 *     Sonatype, Inc. - ongoing development
 ******************************************************************************/

package org.eclipse.equinox.p2.ui;

import java.net.URI;
import java.util.Collection;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
import org.eclipse.equinox.internal.p2.ui.*;
import org.eclipse.equinox.internal.p2.ui.dialogs.*;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;

/**
 * ProvisioningUI defines the provisioning session, UI policy, and related services for a
 * provisioning UI.  
 * 
 * @since 2.0
 *
 */
public class ProvisioningUI {

	/**
	 * Return the default ProvisioningUI.  
	 * 
	 * @return the default Provisioning UI.
	 */
	public static ProvisioningUI getDefaultUI() {
		return ProvUIActivator.getDefault().getProvisioningUI();
	}

	private Policy policy;
	private ProvisioningSession session;
	private String profileId;
	private ProvisioningOperationRunner runner;

	/**
	 * Creates a new instance of the provisioning user interface.
	 * 
	 * @param session The current provisioning session
	 * @param profileId The profile that this user interface is operating on
	 * @param policy The user interface policy settings to use
	 */
	public ProvisioningUI(ProvisioningSession session, String profileId, Policy policy) {
		this.policy = policy;
		this.profileId = profileId;
		if (profileId == null)
			this.profileId = IProfileRegistry.SELF;
		this.session = session;
		this.runner = new ProvisioningOperationRunner(this);
		// register this UI with the agent so other UI related agent services can find it
		session.getProvisioningAgent().registerService(ProvisioningUI.class.getName(), this);
	}

	/**
	 * Return the UI policy used for this instance of the UI.
	 * 
	 * @return the UI policy, must not be <code>null</code>
	 */
	public Policy getPolicy() {
		return policy;
	}

	/**
	 * Return the provisioning session that should be used to obtain
	 * provisioning services.
	 * 
	 * @return the provisioning session, must not be <code>null</code>
	 */
	public ProvisioningSession getSession() {
		return session;
	}

	/**
	 * Return the license manager that should be used to remember
	 * accepted user licenses.
	 * @return  the license manager.  May be <code>null</code> if licenses are not
	 * to be remembered.
	 */
	public LicenseManager getLicenseManager() {
		return (LicenseManager) ServiceHelper.getService(ProvUIActivator.getContext(), LicenseManager.class.getName());
	}

	/**
	 * Return the repository tracker that should be used to add, remove, and track the
	 * statuses of known repositories.
	 * 
	 * @return the repository tracker, must not be <code>null</code>
	 */
	public RepositoryTracker getRepositoryTracker() {
		return (RepositoryTracker) session.getProvisioningAgent().getService(RepositoryTracker.class.getName());
	}

	/**
	 * Return the profile id that should be assumed for this ProvisioningUI if no other
	 * id is otherwise specified.  Some UI classes are assigned a profile id, while others 
	 * are not.  For those classes that are not assigned a current profile id, this id can
	 * be used to obtain one.
	 * 
	 * @return a profile id
	 */
	public String getProfileId() {
		return profileId;
	}

	public LuckyOperation getLuckyOperation(ProvisioningContext context) {
		LuckyOperation luckyOperation = new LuckyOperation(getSession());
		luckyOperation.setProfileId(getProfileId());
		luckyOperation.setProvisioningContext(context);
		return luckyOperation;
	}

	/**
	 * Return an install operation that describes installing the specified IInstallableUnits from the
	 * provided list of repositories.
	 * 
	 * @param iusToInstall the IInstallableUnits to be installed
	 * @param repositories the repositories to use for the operation
	 * @return the install operation
	 */
	public InstallOperation getInstallOperation(Collection<IInstallableUnit> iusToInstall, URI[] repositories) {
		InstallOperation op = new InstallOperation(getSession(), iusToInstall);
		op.setProfileId(getProfileId());
		op.setProvisioningContext(makeProvisioningContext(repositories));
		return op;
	}

	/**
	 * Return an update operation that describes updating the specified IInstallableUnits from the
	 * provided list of repositories.
	 * 
	 * @param iusToUpdate the IInstallableUnits to be updated
	 * @param repositories the repositories to use for the operation
	 * @return the update operation
	 */
	public UpdateOperation getUpdateOperation(Collection<IInstallableUnit> iusToUpdate, URI[] repositories) {
		UpdateOperation op = new UpdateOperation(getSession(), iusToUpdate);
		op.setProfileId(getProfileId());
		op.setProvisioningContext(makeProvisioningContext(repositories));
		return op;
	}

	/**
	 * Return an uninstall operation that describes uninstalling the specified IInstallableUnits, using
	 * the supplied repositories to replace any metadata that must be retrieved for the uninstall.
	 * 
	 * @param iusToUninstall the IInstallableUnits to be installed
	 * @param repositories the repositories to use for the operation
	 * @return the uninstall operation
	 */
	public UninstallOperation getUninstallOperation(Collection<IInstallableUnit> iusToUninstall, URI[] repositories) {
		UninstallOperation op = new UninstallOperation(getSession(), iusToUninstall);
		op.setProfileId(getProfileId());
		op.setProvisioningContext(makeProvisioningContext(repositories));
		return op;
	}

	private ProvisioningContext makeProvisioningContext(URI[] repos) {
		if (repos != null) {
			ProvisioningContext context = new ProvisioningContext(getSession().getProvisioningAgent());
			context.setMetadataRepositories(repos);
			context.setArtifactRepositories(repos);
			return context;
		}
		// look everywhere
		return new ProvisioningContext(getSession().getProvisioningAgent());
	}

	/**
	 * Open an install wizard for installing the specified IInstallableUnits
	 * 
	 * @param initialSelections the IInstallableUnits that should be selected when the wizard opens.  May be <code>null</code>.
	 * @param operation the operation describing the proposed install.  If this operation is not <code>null</code>, then a wizard showing
	 * only the IInstallableUnits described in the operation will be shown.  If the operation is <code>null</code>, then a
	 * wizard allowing the user to browse the repositories will be opened.
	 * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
	 * an in-memory repository reference to the wizard.
	 * 
	 * @return the wizard return code
	 */
	public int openInstallWizard(Collection<IInstallableUnit> initialSelections, InstallOperation operation, LoadMetadataRepositoryJob job) {
		if (operation == null) {
			InstallWizard wizard = new InstallWizard(this, operation, initialSelections, job);
			WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
			dialog.create();
			PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.INSTALL_WIZARD);
			return dialog.open();
		}
		PreselectedIUInstallWizard wizard = new PreselectedIUInstallWizard(this, operation, initialSelections, job);
		WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
		dialog.create();
		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.INSTALL_WIZARD);
		return dialog.open();
	}

	/**
	 * Open an update wizard for the specified update operation.
	 * 
	 * @param skipSelectionsPage <code>true</code> if the selection page should be skipped so that the user is 
	 * viewing the resolution results.  <code>false</code> if the update selection page should be shown first.
	 * @param operation the operation describing the proposed update.  Must not be <code>null</code>.
	 * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
	 * an in-memory repository reference to the wizard.
	 * 
	 * @return the wizard return code
	 */
	public int openUpdateWizard(boolean skipSelectionsPage, UpdateOperation operation, LoadMetadataRepositoryJob job) {
		if (getPolicy().getUpdateWizardStyle() == Policy.UPDATE_STYLE_SINGLE_IUS && UpdateSingleIUWizard.validFor(operation)) {
			UpdateSingleIUWizard wizard = new UpdateSingleIUWizard(this, operation);
			WizardDialog dialog = new WizardDialog(ProvUI.getDefaultParentShell(), wizard);
			dialog.create();
			// TODO do we need a hook for providing custom help?  Or would this just be shown in the update browser?
			return dialog.open();
		}
		UpdateWizard wizard = new UpdateWizard(this, operation, operation.getSelectedUpdates(), job);
		wizard.setSkipSelectionsPage(skipSelectionsPage);
		WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
		dialog.create();
		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UPDATE_WIZARD);
		if (wizard.getCurrentStatus().getSeverity() == IStatus.ERROR) {
			wizard.deselectLockedIUs();
		}
		return dialog.open();

	}

	/**
	 * Open an uninstall wizard for the specified uninstall operation.
	 * 
	 * @param initialSelections the IInstallableUnits that should be selected when the wizard opens.  May be <code>null</code>.
	 * @param operation the operation describing the proposed uninstall.  Must not be <code>null</code>.
	 * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
	 * an in-memory repository reference to the wizard.
	 * 
	 * @return the wizard return code
	 */
	public int openUninstallWizard(Collection<IInstallableUnit> initialSelections, UninstallOperation operation, LoadMetadataRepositoryJob job) {
		UninstallWizard wizard = new UninstallWizard(this, operation, initialSelections, job);
		WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
		dialog.create();
		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UNINSTALL_WIZARD);
		return dialog.open();
	}

	/**
	 * Open a UI that allows the user to manipulate the repositories.
	 * @param shell the shell that should parent the UI
	 */
	public void manipulateRepositories(Shell shell) {
		if (policy.getRepositoryPreferencePageId() != null) {
			PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(shell, policy.getRepositoryPreferencePageId(), null, null);
			dialog.open();
		} else {
			TitleAreaDialog dialog = new TitleAreaDialog(shell) {
				RepositoryManipulationPage page;

				protected Control createDialogArea(Composite parent) {
					page = new RepositoryManipulationPage();
					page.setProvisioningUI(ProvisioningUI.this);
					page.init(PlatformUI.getWorkbench());
					page.createControl(parent);
					this.setTitle(ProvUIMessages.RepositoryManipulationPage_Title);
					this.setMessage(ProvUIMessages.RepositoryManipulationPage_Description);

					Control control = page.getControl();
					control.setLayoutData(new GridData(GridData.FILL_BOTH));
					return page.getControl();
				}

				protected boolean isResizable() {
					return true;
				}

				protected void okPressed() {
					if (page.performOk())
						super.okPressed();
				}

				protected void cancelPressed() {
					if (page.performCancel())
						super.cancelPressed();
				}
			};
			dialog.open();
		}
	}

	/**
	 * Schedule a job to execute the supplied ProvisioningOperation.
	 * 
	 * @param job The operation to execute
	 * @param errorStyle the flags passed to the StatusManager for error reporting
	 */
	public void schedule(final ProvisioningJob job, final int errorStyle) {
		job.setUser(true);
		runner.schedule(job, errorStyle);
	}

	/**
	 * Manage the supplied job as a provisioning operation.  This will allow
	 * the ProvisioningUI to be aware that a provisioning job is running, as well
	 * as manage the restart behavior for the job.
	 * 
	 * @param job the job to be managed
	 * @param jobRestartPolicy an integer constant specifying whether the
	 * supplied job should cause a restart of the system.  The UI Policy's
	 * restart policy is used in conjunction with this constant to determine
	 * what actually occurs when a job completes.
	 * 
	 * @see ProvisioningJob#RESTART_NONE
	 * @see ProvisioningJob#RESTART_ONLY
	 * @see ProvisioningJob#RESTART_OR_APPLY
	 */
	public void manageJob(Job job, final int jobRestartPolicy) {
		runner.manageJob(job, jobRestartPolicy);
	}

	/**
	 * Return a boolean indicating whether the receiver has scheduled any operations
	 * for the profile under management.
	 * 
	 * @return <code>true</code> if other provisioning operations have been scheduled,
	 * <code>false</code> if there are no operations scheduled.
	 */
	public boolean hasScheduledOperations() {
		return getSession().hasScheduledOperationsFor(profileId);
	}

	/**
	 * This method is for automated testing only.
	 * @return the provisioning operation that can suppress restart for automated testing.
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public ProvisioningOperationRunner getOperationRunner() {
		return runner;
	}

	/**
	 * Signal that a repository operation is about to begin.  This allows clients to ignore intermediate
	 * events until the operation is completed.  Callers are responsible for ensuring that
	 * a corresponding operation ending event is signaled.
	 */
	public void signalRepositoryOperationStart() {
		runner.eventBatchCount++;
		if (Tracing.DEBUG_EVENTS_CLIENT)
			Tracing.debug("Batch Count Incremented to:  " + Integer.toString(runner.eventBatchCount)); //$NON-NLS-1$
		ProvUI.getProvisioningEventBus(getSession()).publishEvent(new RepositoryOperationBeginningEvent(this));
	}

	/**
	 * Signal that a repository operation has completed.
	 * 
	 * @param event a {@link RepositoryEvent} that describes the overall operation.  May be <code>null</code>, which
	 * indicates that there was no single event that can describe the operation.  
	 * @param update <code>true</code> if the event should be reflected in the UI, false if it should be ignored.
	 */
	public void signalRepositoryOperationComplete(RepositoryEvent event, boolean update) {
		runner.eventBatchCount--;
		if (Tracing.DEBUG_EVENTS_CLIENT)
			Tracing.debug("Batch Count Decremented to:  " + Integer.toString(runner.eventBatchCount)); //$NON-NLS-1$
		ProvUI.getProvisioningEventBus(getSession()).publishEvent(new RepositoryOperationEndingEvent(this, update, event));
	}

	/**
	 * Load the specified metadata repository, signaling a repository operation start event
	 * before loading, and a repository operation complete event after loading.
	 * 
	 * @param location the location of the repository
	 * @param notify <code>true</code> if the UI should be updated as a result of the load, <code>false</code> if it should not
	 * @param monitor the progress monitor to be used
	 * @return the repository
	 * @throws ProvisionException if the repository could not be loaded
	 */

	public IMetadataRepository loadMetadataRepository(URI location, boolean notify, IProgressMonitor monitor) throws ProvisionException {
		IMetadataRepository repo = null;
		try {
			signalRepositoryOperationStart();
			IMetadataRepositoryManager manager = ProvUI.getMetadataRepositoryManager(getSession());
			repo = manager.loadRepository(location, monitor);
			// If there is no user nickname assigned to this repo but there is a provider name, then set the nickname.
			// This will keep the name in the manager even when the repo is not loaded
			String name = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
			if (name == null || name.length() == 0) {
				name = repo.getName();
				if (name != null && name.length() > 0)
					manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name);
			}
		} catch (ProvisionException e) {
			getRepositoryTracker().reportLoadFailure(location, e);
		} finally {
			// We have no idea how many repos may have been touched as a result of loading this one.
			signalRepositoryOperationComplete(null, notify);
		}
		return repo;
	}

	/**
	 * Load the specified artifact repository, signaling a repository operation start event
	 * before loading, and a repository operation complete event after loading.
	 * 
	 * @param location the location of the repository
	 * @param update <code>true</code> if the UI should be updated as a result of the load, <code>false</code> if it should not
	 * @param monitor the progress monitor to be used
	 * @return the repository
	 * @throws ProvisionException if the repository could not be loaded
	 */
	public IArtifactRepository loadArtifactRepository(URI location, boolean update, IProgressMonitor monitor) throws ProvisionException {
		IArtifactRepository repo;
		signalRepositoryOperationStart();
		try {
			IArtifactRepositoryManager manager = ProvUI.getArtifactRepositoryManager(getSession());
			repo = manager.loadRepository(location, monitor);

			// If there is no user nickname assigned to this repo but there is a provider name, then set the nickname.
			// This will keep the name in the manager even when the repo is not loaded
			String name = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
			if (name == null) {
				name = manager.getRepositoryProperty(location, IRepository.PROP_NAME);
				if (name != null)
					manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name);
			}
		} finally {
			// We have no idea how many repos may have been touched as a result of loading this one,
			// so we do not use a specific repository event to represent it.
			signalRepositoryOperationComplete(null, update);
		}
		return repo;
	}
}
