/*
 * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) 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:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.oomph.p2.internal.core;

import org.eclipse.oomph.p2.P2Exception;
import org.eclipse.oomph.p2.ProfileDefinition;
import org.eclipse.oomph.p2.Repository;
import org.eclipse.oomph.p2.Requirement;
import org.eclipse.oomph.p2.core.Agent;
import org.eclipse.oomph.p2.core.BundlePool;
import org.eclipse.oomph.p2.core.P2Util;
import org.eclipse.oomph.p2.core.Profile;
import org.eclipse.oomph.p2.core.ProfileTransaction;
import org.eclipse.oomph.p2.core.ProfileTransaction.CommitContext.DeltaType;
import org.eclipse.oomph.p2.core.ProfileTransaction.CommitContext.ResolutionInfo;
import org.eclipse.oomph.util.Confirmer;
import org.eclipse.oomph.util.Confirmer.Confirmation;
import org.eclipse.oomph.util.ObjectUtil;
import org.eclipse.oomph.util.Pair;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.oomph.util.WorkerPool;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.EqualityHelper;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.ProgressMonitorWrapper;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
import org.eclipse.equinox.internal.p2.director.SimplePlanner;
import org.eclipse.equinox.internal.p2.engine.InstallableUnitOperand;
import org.eclipse.equinox.internal.p2.engine.InstallableUnitPropertyOperand;
import org.eclipse.equinox.internal.p2.engine.Operand;
import org.eclipse.equinox.internal.p2.engine.PropertyOperand;
import org.eclipse.equinox.internal.p2.engine.ProvisioningPlan;
import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
import org.eclipse.equinox.internal.p2.touchpoint.natives.BackupStore;
import org.eclipse.equinox.internal.p2.touchpoint.natives.IBackupStore;
import org.eclipse.equinox.internal.p2.touchpoint.natives.NativeTouchpoint;
import org.eclipse.equinox.internal.provisional.p2.director.PlanExecutionHelper;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.core.UIServices;
import org.eclipse.equinox.p2.engine.IEngine;
import org.eclipse.equinox.p2.engine.IPhaseSet;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.IProvisioningPlan;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.planner.IPlanner;
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
import org.eclipse.equinox.p2.planner.ProfileInclusionRules;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.osgi.service.datalocation.Location;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URI;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Eike Stepper
 */
@SuppressWarnings("restriction")
public class ProfileTransactionImpl implements ProfileTransaction
{
  public static final String PROP_ADDITIONAL_POOLS = "oomph.p2.additional.pools";

  public static final String ARTIFICIAL_ROOT_ID = "artificial_root";

  private static final String OSGI_RESOLVER_USES_MODE = "osgi.resolver.usesMode";

  private static final String SOURCE_IU_ID = "org.eclipse.oomph.p2.source.container"; //$NON-NLS-1$

  private static final IRequirement BUNDLE_REQUIREMENT = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, //$NON-NLS-1$ //$NON-NLS-2$
      false, false);

  private static final Set<String> IMMUTABLE_PROPERTIES = new HashSet<String>(Arrays.asList(Profile.PROP_INSTALL_FEATURES, Profile.PROP_INSTALL_FOLDER,
      Profile.PROP_CACHE, Profile.PROP_PROFILE_TYPE, Profile.PROP_PROFILE_DEFINITION));

  private final Profile profile;

  private final ProfileDefinition profileDefinition;

  private final ProfileDefinition cleanProfileDefinition;

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

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

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

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

  private boolean removeAll;

  private boolean mirrors;

  private boolean committed;

  public ProfileTransactionImpl(Profile profile)
  {
    this.profile = profile;

    cleanProfileDefinition = profile.getDefinition();
    profileDefinition = EcoreUtil.copy(cleanProfileDefinition);

    cleanProfileProperties.putAll(profile.getProperties());
    cleanProfileProperties.remove(Profile.PROP_INSTALL_FOLDER);
    cleanProfileProperties.remove(Profile.PROP_CACHE);
    cleanProfileProperties.remove(Profile.PROP_PROFILE_DEFINITION);
    profileProperties.putAll(cleanProfileProperties);

    for (IInstallableUnit iu : P2Util.asIterable(profile.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())))
    {
      Map<String, String> properties = profile.getInstallableUnitProperties(iu);
      if (!properties.isEmpty())
      {
        for (Map.Entry<String, String> property : properties.entrySet())
        {
          String key = property.getKey();
          String value = property.getValue();
          cleanIUProperties.put(new IUPropertyKey(iu, key), value);
        }
      }
    }

    iuProperties.putAll(cleanIUProperties);

    mirrors = SimpleArtifactRepository.MIRRORS_ENABLED;
  }

  public Profile getProfile()
  {
    return profile;
  }

  public ProfileDefinition getProfileDefinition()
  {
    return profileDefinition;
  }

  public String getProfileProperty(String key)
  {
    return profileProperties.get(key);
  }

  public ProfileTransaction setProfileProperty(String key, String value)
  {
    if (IMMUTABLE_PROPERTIES.contains(key) && !ObjectUtil.equals(profileProperties.get(key), value))
    {
      throw new IllegalArgumentException("Property is immutable: " + key);
    }

    if (value != null)
    {
      profileProperties.put(key, value);
    }
    else
    {
      profileProperties.remove(key);
    }

    return this;
  }

  public ProfileTransaction removeProfileProperty(String key)
  {
    return setProfileProperty(key, null);
  }

  public String getInstallableUnitProperty(IInstallableUnit iu, String key)
  {
    return iuProperties.get(new IUPropertyKey(iu, key));
  }

  public ProfileTransaction setInstallableUnitProperty(IInstallableUnit iu, String key, String value)
  {
    IUPropertyKey propertyKey = new IUPropertyKey(iu, key);
    if (value != null)
    {
      iuProperties.put(propertyKey, value);
    }
    else
    {
      iuProperties.remove(propertyKey);
    }

    return this;
  }

  public ProfileTransaction removeInstallableUnitProperty(IInstallableUnit iu, String key)
  {
    return setInstallableUnitProperty(iu, key, null);
  }

  public boolean isRemoveExistingInstallableUnits()
  {
    return removeAll;
  }

  public ProfileTransaction setRemoveExistingInstallableUnits(boolean removeAll)
  {
    this.removeAll = removeAll;
    return this;
  }

  public boolean isMirrors()
  {
    return mirrors;
  }

  public ProfileTransaction setMirrors(boolean mirrors)
  {
    this.mirrors = mirrors;
    return this;
  }

  public boolean isDirty()
  {
    if (removeAll)
    {
      return true;
    }

    if (!profileProperties.equals(cleanProfileProperties))
    {
      return true;
    }

    if (!iuProperties.equals(cleanIUProperties))
    {
      return true;
    }

    return isProfileDefinitionChanged();
  }

  private boolean isProfileDefinitionChanged()
  {
    if (profileDefinition.isIncludeSourceBundles() != cleanProfileDefinition.isIncludeSourceBundles())
    {
      return true;
    }

    EqualityHelper equalityHelper = new EqualityHelper();
    if (!equals(equalityHelper, profileDefinition.getRequirements(), cleanProfileDefinition.getRequirements()))
    {
      return true;
    }

    if (!equals(equalityHelper, profileDefinition.getRepositories(), cleanProfileDefinition.getRepositories()))
    {
      return true;
    }

    return false;
  }

  public boolean commit() throws CoreException
  {
    return commit(null, null);
  }

  public boolean commit(IProgressMonitor monitor) throws CoreException
  {
    return commit(null, monitor);
  }

  public boolean commit(CommitContext commitContext, IProgressMonitor monitor) throws CoreException
  {
    if (!committed)
    {
      committed = true;
      monitor.beginTask("", 2);

      try
      {
        Resolution resolution = resolve(commitContext, new SubProgressMonitor(monitor, 1));
        if (resolution != null)
        {
          return resolution.commit(new SubProgressMonitor(monitor, 1));
        }

        monitor.worked(1);
      }
      finally
      {
        monitor.done();
      }
    }

    return false;
  }

  public Resolution resolve(IProgressMonitor monitor) throws CoreException
  {
    return resolve(null, monitor);
  }

  public Resolution resolve(CommitContext commitContext, IProgressMonitor monitor) throws CoreException
  {
    final CommitContext context = commitContext == null ? new CommitContext() : commitContext;
    if (monitor == null)
    {
      monitor = new NullProgressMonitor();
    }

    final Agent agent = profile.getAgent();
    final List<Runnable> cleanup = new ArrayList<Runnable>();

    boolean includeSourceBundles = profileDefinition.isIncludeSourceBundles();
    monitor.beginTask("", includeSourceBundles ? 75 : 70);

    try
    {
      initMirrors(cleanup);

      final List<IMetadataRepository> metadataRepositories = new ArrayList<IMetadataRepository>();
      Set<URI> artifactURIs = new HashSet<URI>();
      URI[] metadataURIs = collectRepositories(metadataRepositories, artifactURIs, cleanup, new SubProgressMonitor(monitor, 50));

      final ProfileImpl profileImpl = (ProfileImpl)profile;
      final IProfile delegate = profileImpl.getDelegate();
      final long timestamp = delegate.getTimestamp();

      IPlanner planner = agent.getPlanner();
      IProfileChangeRequest profileChangeRequest = planner.createChangeRequest(delegate);
      final IInstallableUnit rootIU = adjustProfileChangeRequest(profileChangeRequest, new SubProgressMonitor(monitor, 5));

      final ProvisioningContext provisioningContext = context.createProvisioningContext(this, profileChangeRequest);
      provisioningContext.setMetadataRepositories(metadataURIs);
      provisioningContext.setArtifactRepositories(artifactURIs.toArray(new URI[artifactURIs.size()]));

      IQueryable<IInstallableUnit> metadata = provisioningContext.getMetadata(new SubProgressMonitor(monitor, 5));

      final IProvisioningPlan provisioningPlan = planner.getProvisioningPlan(profileChangeRequest, provisioningContext, new SubProgressMonitor(monitor, 10));
      P2CorePlugin.INSTANCE.coreException(provisioningPlan.getStatus());

      IQueryable<IInstallableUnit> futureState = provisioningPlan.getFutureState();
      for (IRequirement requirement : rootIU.getRequirements())
      {
        if (requirement instanceof IRequiredCapability)
        {
          IRequiredCapability requiredCapability = (IRequiredCapability)requirement;
          for (IInstallableUnit installableUnit : P2Util
              .asIterable(futureState.query(QueryUtil.createIUQuery(requiredCapability.getName(), requiredCapability.getRange()), null)))
          {
            provisioningPlan.setInstallableUnitProfileProperty(installableUnit, Profile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
            provisioningPlan.setInstallableUnitProfileProperty(installableUnit, SimplePlanner.INCLUSION_RULES,
                ProfileInclusionRules.createStrictInclusionRule(installableUnit));
          }
        }
      }

      if (includeSourceBundles)
      {
        IInstallableUnit sourceContainerIU = generateSourceContainerIU(provisioningPlan, metadata, new SubProgressMonitor(monitor, 5));
        provisioningPlan.addInstallableUnit(sourceContainerIU);
        provisioningPlan.setInstallableUnitProfileProperty(sourceContainerIU, Profile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
      }

      final Map<IInstallableUnit, CommitContext.DeltaType> iuDeltas = new HashMap<IInstallableUnit, CommitContext.DeltaType>();
      final Map<IInstallableUnit, Map<String, Pair<Object, Object>>> propertyDeltas = new HashMap<IInstallableUnit, Map<String, Pair<Object, Object>>>();
      computeOperandDeltas(provisioningPlan, iuDeltas, propertyDeltas);

      ResolutionInfo resolutionInfo = new ResolutionInfo()
      {
        public IProvisioningPlan getProvisioningPlan()
        {
          return provisioningPlan;
        }

        public IInstallableUnit getArtificialRoot()
        {
          return rootIU;
        }

        public Map<IInstallableUnit, DeltaType> getIUDeltas()
        {
          return iuDeltas;
        }

        public Map<IInstallableUnit, Map<String, Pair<Object, Object>>> getPropertyDeltas()
        {
          return propertyDeltas;
        }

        public List<IMetadataRepository> getMetadataRepositories()
        {
          return metadataRepositories;
        }
      };

      if (!context.handleProvisioningPlan(resolutionInfo))
      {
        return null;
      }

      if (iuDeltas.isEmpty() && propertyDeltas.isEmpty())
      {
        return null;
      }

      return new Resolution()
      {
        public ProfileTransaction getProfileTransaction()
        {
          return ProfileTransactionImpl.this;
        }

        public IProvisioningPlan getProvisioningPlan()
        {
          return provisioningPlan;
        }

        public boolean commit(IProgressMonitor monitor) throws CoreException
        {
          final String oldUsesMode = System.setProperty(OSGI_RESOLVER_USES_MODE, "ignore");
          cleanup.add(new Runnable()
          {
            public void run()
            {
              if (oldUsesMode == null)
              {
                System.clearProperty(OSGI_RESOLVER_USES_MODE);
              }
              else
              {
                System.setProperty(OSGI_RESOLVER_USES_MODE, oldUsesMode);
              }
            }
          });

          try
          {
            IPhaseSet phaseSet = context.getPhaseSet(ProfileTransactionImpl.this);

            initUnsignedContentConfirmer(context, agent, cleanup);

            IEngine engine = agent.getEngine();
            ensureSameBackupDevice(provisioningPlan);

            IStatus status = PlanExecutionHelper.executePlan(provisioningPlan, engine, phaseSet, provisioningContext,
                new ExecutePlanMonitor(monitor, provisioningPlan));

            context.handleExecutionResult(status);
            P2CorePlugin.INSTANCE.coreException(status);

            profileImpl.setDefinition(profileDefinition);
            return delegate.getTimestamp() != timestamp;
          }
          finally
          {
            cleanup(cleanup);
          }
        }

        public void rollback()
        {
          cleanup(cleanup);
        }
      };
    }
    catch (Throwable t)
    {
      cleanup(cleanup);
      P2CorePlugin.INSTANCE.coreException(t);
      return null;
    }
    finally
    {
      monitor.done();
    }
  }

  private void computeOperandDeltas(final IProvisioningPlan provisioningPlan, Map<IInstallableUnit, CommitContext.DeltaType> iuDeltas,
      Map<IInstallableUnit, Map<String, Pair<Object, Object>>> propertyDeltas)
  {
    // Undo (remove) the addition of our artificial root IU and compute the effective deltas (to remove redundancies in the operands).
    Field operandsField = ReflectUtil.getField(ProvisioningPlan.class, "operands");
    @SuppressWarnings("unchecked")
    List<Operand> operands = (List<Operand>)ReflectUtil.getValue(operandsField, provisioningPlan);
    for (Iterator<Operand> it = operands.iterator(); it.hasNext();)
    {
      Operand operand = it.next();
      if (operand instanceof InstallableUnitOperand)
      {
        InstallableUnitOperand iuOperand = (InstallableUnitOperand)operand;
        IInstallableUnit first = iuOperand.first();
        IInstallableUnit second = iuOperand.second();
        if (first == null)
        {
          if (second.getId().equals(ARTIFICIAL_ROOT_ID))
          {
            it.remove();
          }
          else
          {
            iuDeltas.put(second, CommitContext.DeltaType.ADDITION);
          }
        }
        else
        {
          iuDeltas.put(first, CommitContext.DeltaType.REMOVAL);
          if (second != null)
          {
            iuDeltas.put(second, CommitContext.DeltaType.ADDITION);
          }
        }
      }
      else if (operand instanceof InstallableUnitPropertyOperand)
      {
        InstallableUnitPropertyOperand iuPropertyOperand = (InstallableUnitPropertyOperand)operand;
        IInstallableUnit operandIU = iuPropertyOperand.getInstallableUnit();
        if (operandIU.getId().equals(ARTIFICIAL_ROOT_ID))
        {
          it.remove();
        }
        else
        {
          Object first = iuPropertyOperand.first();
          Object second = iuPropertyOperand.second();
          String key = iuPropertyOperand.getKey();
          populatePropertyDeltas(operandIU, first, second, key, propertyDeltas);
        }
      }
      else if (operand instanceof PropertyOperand)
      {
        PropertyOperand propertyOperand = (PropertyOperand)operand;
        Object first = propertyOperand.first();
        Object second = propertyOperand.second();
        String key = propertyOperand.getKey();
        populatePropertyDeltas(null, first, second, key, propertyDeltas);
      }
    }

    for (Iterator<Map.Entry<IInstallableUnit, Map<String, Pair<Object, Object>>>> it = propertyDeltas.entrySet().iterator(); it.hasNext();)
    {
      Map.Entry<IInstallableUnit, Map<String, Pair<Object, Object>>> entry = it.next();
      Set<Map.Entry<String, Pair<Object, Object>>> properties = entry.getValue().entrySet();
      for (Iterator<Map.Entry<String, Pair<Object, Object>>> it2 = properties.iterator(); it2.hasNext();)
      {
        Map.Entry<String, Pair<Object, Object>> property = it2.next();
        Pair<Object, Object> pair = property.getValue();
        if (ObjectUtil.equals(pair.getElement1(), pair.getElement2()))
        {
          it2.remove();
        }
      }

      if (properties.isEmpty())
      {
        it.remove();
      }
    }
  }

  private void populatePropertyDeltas(IInstallableUnit operandIU, Object first, Object second, String key,
      Map<IInstallableUnit, Map<String, Pair<Object, Object>>> propertyDeltas)
  {
    Map<String, Pair<Object, Object>> propertyDelta = propertyDeltas.get(operandIU);
    if (propertyDelta == null)
    {
      propertyDelta = new HashMap<String, Pair<Object, Object>>();
      propertyDelta.put(key, new Pair<Object, Object>(first, second));
      propertyDeltas.put(operandIU, propertyDelta);
    }
    else
    {
      Pair<Object, Object> pair = propertyDelta.get(key);
      if (pair == null)
      {
        propertyDelta.put(key, new Pair<Object, Object>(first, second));
      }
      else
      {
        pair.setElement2(second);
      }
    }
  }

  private void initMirrors(final List<Runnable> cleanup)
  {
    final boolean wasMirrors = SimpleArtifactRepository.MIRRORS_ENABLED;
    if (mirrors != wasMirrors)
    {
      try
      {
        final Field mirrorsEnabledField = ReflectUtil.getField(SimpleArtifactRepository.class, "MIRRORS_ENABLED");
        ReflectUtil.setValue(mirrorsEnabledField, null, mirrors, true);

        cleanup.add(new Runnable()
        {
          public void run()
          {
            try
            {
              ReflectUtil.setValue(mirrorsEnabledField, null, wasMirrors, true);
            }
            catch (Throwable ex)
            {
              // Ignore
            }
          }
        });
      }
      catch (Throwable ex)
      {
        // Ignore
      }
    }
  }

  private void initUnsignedContentConfirmer(final CommitContext context, final Agent agent, final List<Runnable> cleanup)
  {
    final Confirmer unsignedContentConfirmer = context.getUnsignedContentConfirmer();
    if (unsignedContentConfirmer != null)
    {
      final IProvisioningAgent provisioningAgent = agent.getProvisioningAgent();
      final UIServices oldUIServices = (UIServices)provisioningAgent.getService(UIServices.SERVICE_NAME);
      final UIServices newUIServices = new UIServices()
      {
        @Override
        public AuthenticationInfo getUsernamePassword(String location)
        {
          if (oldUIServices != null)
          {
            return oldUIServices.getUsernamePassword(location);
          }

          return null;
        }

        @Override
        public AuthenticationInfo getUsernamePassword(String location, AuthenticationInfo previousInfo)
        {
          if (oldUIServices != null)
          {
            return oldUIServices.getUsernamePassword(location, previousInfo);
          }

          return null;
        }

        @Override
        public TrustInfo getTrustInfo(Certificate[][] untrustedChains, String[] unsignedDetail)
        {
          if (unsignedDetail != null && unsignedDetail.length != 0)
          {
            Confirmation confirmation = unsignedContentConfirmer.confirm(true, unsignedDetail);
            if (!confirmation.isConfirmed())
            {
              return new TrustInfo(new Certificate[0], false, false);
            }

            // We've checked trust already; prevent oldUIServices to check it again.
            unsignedDetail = null;
          }

          if (oldUIServices != null)
          {
            return oldUIServices.getTrustInfo(untrustedChains, unsignedDetail);
          }

          // The rest is copied from org.eclipse.equinox.internal.p2.director.app.DirectorApplication.AvoidTrustPromptService
          final Certificate[] trusted;
          if (untrustedChains == null)
          {
            trusted = null;
          }
          else
          {
            trusted = new Certificate[untrustedChains.length];
            for (int i = 0; i < untrustedChains.length; i++)
            {
              trusted[i] = untrustedChains[i][0];
            }
          }

          return new TrustInfo(trusted, false, true);
        }
      };

      provisioningAgent.registerService(UIServices.SERVICE_NAME, newUIServices);

      cleanup.add(new Runnable()
      {
        public void run()
        {
          provisioningAgent.unregisterService(UIServices.SERVICE_NAME, newUIServices);
          if (oldUIServices != null)
          {
            provisioningAgent.registerService(UIServices.SERVICE_NAME, oldUIServices);
          }
        }
      });
    }
  }

  private URI[] collectRepositories(List<IMetadataRepository> metadataRepositories, Set<URI> artifactURIs, List<Runnable> cleanup, IProgressMonitor monitor)
      throws CoreException
  {
    Agent agent = profile.getAgent();
    final IMetadataRepositoryManager manager = agent.getMetadataRepositoryManager();
    Set<String> knownRepositories = P2Util.getKnownRepositories(manager);

    EList<Repository> repositories = profileDefinition.getRepositories();
    URI[] metadataURIs = new URI[repositories.size()];
    Set<URI> addedArtifactURIs = new HashSet<URI>();

    for (int i = 0; i < metadataURIs.length; i++)
    {
      try
      {
        Repository repository = repositories.get(i);
        String url = repository.getURL();
        final URI uri = new URI(url);

        if (!knownRepositories.contains(url))
        {
          cleanup.add(new Runnable()
          {
            public void run()
            {
              manager.removeRepository(uri);
            }
          });
        }

        metadataURIs[i] = uri;

        if (addedArtifactURIs.add(uri))
        {
          artifactURIs.add(uri);
        }
      }
      catch (Exception ex)
      {
        throw new P2Exception(ex);
      }
    }

    RepositoryLoader repositoryLoader = new RepositoryLoader(manager, metadataURIs);
    repositoryLoader.begin(monitor);
    ProvisionException exception = repositoryLoader.getException();
    if (exception != null)
    {
      throw exception;
    }

    if (repositoryLoader.isCanceled())
    {
      throw new OperationCanceledException();
    }

    for (int i = 0; i < metadataURIs.length; i++)
    {
      IMetadataRepository metadataRepository = manager.loadRepository(metadataURIs[i], null);
      metadataRepositories.add(metadataRepository);
    }

    if (!"false".equalsIgnoreCase(PropertiesUtil.getProperty(PROP_ADDITIONAL_POOLS)))
    {
      for (BundlePool bundlePool : agent.getAgentManager().getBundlePools())
      {
        P2CorePlugin.checkCancelation(monitor);

        if (bundlePool != profile.getBundlePool())
        {
          URI uri = bundlePool.getLocation().toURI();
          if (addedArtifactURIs.add(uri))
          {
            artifactURIs.add(uri);
          }
        }
      }
    }

    return metadataURIs;
  }

  private IInstallableUnit adjustProfileChangeRequest(final IProfileChangeRequest request, IProgressMonitor monitor) throws CoreException
  {
    InstallableUnitDescription rootDescription = new InstallableUnitDescription();
    rootDescription.setId(ARTIFICIAL_ROOT_ID);
    rootDescription.setVersion(Version.createOSGi(1, 0, 0, "v" + System.currentTimeMillis()));
    rootDescription.setSingleton(true);
    rootDescription.setArtifacts(new IArtifactKey[0]);
    rootDescription.setProperty(InstallableUnitDescription.PROP_TYPE_GROUP, Boolean.TRUE.toString());
    rootDescription.setCapabilities(new IProvidedCapability[] {
        MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, rootDescription.getId(), rootDescription.getVersion()) });
    List<IRequirement> rootRequirements = new ArrayList<IRequirement>();

    Map<String, IInstallableUnit> rootIUs = new HashMap<String, IInstallableUnit>();
    for (IInstallableUnit rootIU : P2Util.asIterable(profile.query(new UserVisibleRootQuery(), null)))
    {
      if (!removeAll)
      {
        String id = rootIU.getId();
        rootIUs.put(id, rootIU);

        VersionRange versionRange = getCleanVersionRange(rootIU);
        IMatchExpression<IInstallableUnit> filter = rootIU.getFilter();

        IRequirement rootRequirement = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, id, versionRange, filter, false, false);
        rootRequirements.add(rootRequirement);
      }

      request.remove(rootIU);
    }

    MultiStatus status = new MultiStatus(P2CorePlugin.INSTANCE.getSymbolicName(), 0, "Profile could not be changed", null);

    for (Requirement requirement : profileDefinition.getRequirements())
    {
      P2CorePlugin.checkCancelation(monitor);

      String namespace = requirement.getNamespace();
      String name = requirement.getName();
      VersionRange versionRange = requirement.getVersionRange();
      IMatchExpression<IInstallableUnit> filter = requirement.getMatchExpression();
      boolean optional = requirement.isOptional();

      IRequirement rootRequirement = MetadataFactory.createRequirement(namespace, name, versionRange, filter, optional, false);
      rootRequirements.add(rootRequirement);
    }

    rootDescription.setRequirements(rootRequirements.toArray(new IRequirement[rootRequirements.size()]));

    IInstallableUnit rootUnit = MetadataFactory.createInstallableUnit(rootDescription);
    request.add(rootUnit);
    request.setInstallableUnitProfileProperty(rootUnit, Profile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());

    P2CorePlugin.INSTANCE.coreException(status);

    if (isProfileDefinitionChanged())
    {
      request.setProfileProperty(Profile.PROP_PROFILE_DEFINITION, ProfileImpl.definitionToXML(profileDefinition));
    }

    compare(cleanProfileProperties, profileProperties, new CompareHandler<String>()
    {
      public void handleAddition(String key, String value)
      {
        if (!IMMUTABLE_PROPERTIES.contains(key))
        {
          request.setProfileProperty(key, value);
        }
      }

      public void handleRemoval(String key)
      {
        if (!IMMUTABLE_PROPERTIES.contains(key))
        {
          request.removeProfileProperty(key);
        }
      }
    });

    compare(cleanIUProperties, iuProperties, new CompareHandler<IUPropertyKey>()
    {
      public void handleAddition(IUPropertyKey key, String value)
      {
        request.setInstallableUnitProfileProperty(key.getInstallableUnit(), key.getPropertyKey(), value);
      }

      public void handleRemoval(IUPropertyKey key)
      {
        request.removeInstallableUnitProfileProperty(key.getInstallableUnit(), key.getPropertyKey());
      }
    });

    return rootUnit;
  }

  private VersionRange getCleanVersionRange(IInstallableUnit rootIU)
  {
    String id = rootIU.getId();
    Version version = rootIU.getVersion();
    for (Requirement requirement : cleanProfileDefinition.getRequirements())
    {
      if (requirement.getName().equals(id))
      {
        VersionRange versionRange = requirement.getVersionRange();
        if (versionRange == null || versionRange.isIncluded(version))
        {
          return versionRange;
        }
      }
    }

    return new VersionRange(version.toString());
  }

  private void ensureSameBackupDevice(final IProvisioningPlan provisioningPlan) throws CoreException
  {
    // This is to handle the special case in Windows where the backup store tries to move the *.exe to a different device.
    // This fails when the *.exe is currently in use.
    // The strategy then copies the file instead and then to delete it, but that always fails.
    // If the backup store is on the same device, the move is successful and the *.exe can be successfully updated.
    // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=427148 for more details.
    if (profile.isCurrent() && Platform.OS_WIN32.equals(Platform.getOS()))
    {
      try
      {
        Location location = Platform.getInstallLocation();
        org.eclipse.emf.common.util.URI installationLocation = org.eclipse.emf.common.util.URI.createURI(FileLocator.resolve(location.getURL()).toString());
        org.eclipse.emf.common.util.URI tempDir = org.eclipse.emf.common.util.URI.createFileURI(PropertiesUtil.getProperty("java.io.tmpdir"));
        if (!ObjectUtil.equals(installationLocation.device(), tempDir.device()))
        {
          Field field = ReflectUtil.getField(NativeTouchpoint.class, "backups");
          @SuppressWarnings("unchecked")
          Map<IProfile, IBackupStore> backups = (Map<IProfile, IBackupStore>)ReflectUtil.getValue(field, null);
          final File localTempFolder = new File(installationLocation.toFileString(), "backup");
          final IProfile planProfile = provisioningPlan.getProfile();
          backups.put(planProfile, new IBackupStore()
          {
            private BackupStore delegate;

            public boolean backup(File file) throws IOException
            {
              loadDelegate();
              return delegate.backup(file);
            }

            public boolean backupDirectory(File file) throws IOException
            {
              loadDelegate();
              return delegate.backupDirectory(file);
            }

            public void discard()
            {
              if (delegate == null)
              {
                return;
              }
              delegate.discard();
            }

            public void restore() throws IOException
            {
              if (delegate == null)
              {
                return;
              }
              delegate.restore();
            }

            private void loadDelegate()
            {
              if (delegate != null)
              {
                return;
              }
              delegate = new BackupStore(localTempFolder, NativeTouchpoint.escape(planProfile.getProfileId()));
            }

            public String getBackupName()
            {
              loadDelegate();
              return delegate.getBackupName();
            }

            public boolean backupCopy(File file) throws IOException
            {
              loadDelegate();
              return delegate.backupCopy(file);
            }

            public void backupCopyAll(File file) throws IOException
            {
              loadDelegate();
              delegate.backupCopyAll(file);
            }

            public void backupAll(File file) throws IOException
            {
              loadDelegate();
              delegate.backupAll(file);
            }
          });
        }
      }
      catch (IOException ex)
      {
        P2CorePlugin.INSTANCE.coreException(ex);
      }
    }
  }

  private static void cleanup(List<Runnable> cleanup)
  {
    for (Runnable runnable : cleanup)
    {
      try
      {
        runnable.run();
      }
      catch (Throwable t)
      {
        P2CorePlugin.INSTANCE.log(t);
      }
    }

    cleanup.clear();
  }

  private static IInstallableUnit generateSourceContainerIU(IProvisioningPlan provisioningPlan, IQueryable<IInstallableUnit> metadata, IProgressMonitor monitor)
  {
    // Create and return an IU that has optional and greedy requirements on all source bundles
    // related to bundle IUs in the profile
    List<IRequirement> requirements = new ArrayList<IRequirement>();

    IQueryResult<IInstallableUnit> ius = provisioningPlan.getFutureState().query(QueryUtil.createIUAnyQuery(), monitor);
    for (IInstallableUnit iu : P2Util.asIterable(ius))
    {
      P2CorePlugin.checkCancelation(monitor);

      // TODO What about source features?
      if (iu.satisfies(BUNDLE_REQUIREMENT))
      {
        String id = iu.getId() + ".source";
        Version version = iu.getVersion();
        VersionRange versionRange = new VersionRange(version, true, version, true);

        IInstallableUnit sourceIU = queryInstallableUnit(metadata, id, versionRange, monitor);
        if (sourceIU != null)
        {
          provisioningPlan.addInstallableUnit(sourceIU);

          IRequirement sourceRequirement = MetadataFactory.createRequirement("osgi.bundle", id, versionRange, null, true, false, true);
          requirements.add(sourceRequirement);
        }
      }
    }

    Version sourceContainerIUVersion = getSourceContainerIUVersion(provisioningPlan.getProfile(), monitor);
    IProvidedCapability capability = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, SOURCE_IU_ID, sourceContainerIUVersion);

    InstallableUnitDescription sourceIUDescription = new MetadataFactory.InstallableUnitDescription();
    sourceIUDescription.setSingleton(true);
    sourceIUDescription.setId(SOURCE_IU_ID);
    sourceIUDescription.setVersion(sourceContainerIUVersion);
    sourceIUDescription.addRequirements(requirements);
    sourceIUDescription.setCapabilities(new IProvidedCapability[] { capability });

    return MetadataFactory.createInstallableUnit(sourceIUDescription);
  }

  private static Version getSourceContainerIUVersion(IProfile profile, IProgressMonitor monitor)
  {
    IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(SOURCE_IU_ID);
    IQueryResult<IInstallableUnit> result = profile.query(query, monitor);
    if (result.isEmpty())
    {
      return Version.createOSGi(1, 0, 0);
    }

    IInstallableUnit currentSourceIU = result.iterator().next();
    Integer major = (Integer)currentSourceIU.getVersion().getSegment(0);
    return Version.createOSGi(major.intValue() + 1, 0, 0);
  }

  private static IInstallableUnit queryInstallableUnit(IQueryable<IInstallableUnit> metadata, String id, VersionRange versionRange, IProgressMonitor monitor)
  {
    IQuery<IInstallableUnit> iuQuery = QueryUtil.createIUQuery(id, versionRange);
    IQuery<IInstallableUnit> latestQuery = QueryUtil.createLatestQuery(iuQuery);

    Iterator<IInstallableUnit> iterator = metadata.query(latestQuery, monitor).iterator();
    if (iterator.hasNext())
    {
      return iterator.next();
    }

    return null;
  }

  private static <T extends EObject> boolean equals(EqualityHelper equalityHelper, Collection<T> c1, Collection<T> c2)
  {
    for (T o : c1)
    {
      if (!contains(equalityHelper, c2, o))
      {
        return false;
      }
    }

    for (T o : c2)
    {
      if (!contains(equalityHelper, c1, o))
      {
        return false;
      }
    }

    return true;
  }

  private static <T extends EObject> boolean contains(EqualityHelper equalityHelper, Collection<T> c, T object)
  {
    for (T o : c)
    {
      if (equalityHelper.equals(object, o))
      {
        return true;
      }
    }

    return false;
  }

  private static <K> void compare(Map<K, String> clean, Map<K, String> dirty, CompareHandler<K> handler)
  {
    for (Map.Entry<K, String> entry : dirty.entrySet())
    {
      K key = entry.getKey();
      String dirtyValue = entry.getValue();
      String cleanValue = clean.get(key);

      if (cleanValue == null || !cleanValue.equals(dirtyValue))
      {
        handler.handleAddition(key, dirtyValue);
      }
    }

    for (Map.Entry<K, String> entry : clean.entrySet())
    {
      K key = entry.getKey();
      if (!dirty.containsKey(key))
      {
        handler.handleRemoval(key);
      }
    }
  }

  /**
   * @author Eike Stepper
   */
  private static final class ExecutePlanMonitor extends ProgressMonitorWrapper
  {
    private static final String INSTALLING_PREFIX = "Installing ";

    private final Map<String, LinkedList<Version>> versions = new HashMap<String, LinkedList<Version>>();

    private final IQueryable<IInstallableUnit> additions;

    private ExecutePlanMonitor(IProgressMonitor monitor, IProvisioningPlan provisioningPlan)
    {
      super(monitor);
      additions = provisioningPlan.getAdditions();
    }

    @Override
    public void subTask(String name)
    {
      if (name.startsWith(INSTALLING_PREFIX))
      {
        String id = name.substring(INSTALLING_PREFIX.length());

        Version version = getVersion(id);
        if (version != null)
        {
          name += " [" + version + "]";
        }
      }

      super.subTask(name);
    }

    private Version getVersion(String id)
    {
      LinkedList<Version> list = versions.get(id);
      if (list != null)
      {
        if (list.isEmpty())
        {
          return null;
        }

        return list.remove(0);
      }

      Version firstVersion = null;

      IQueryResult<IInstallableUnit> ius = additions.query(QueryUtil.createIUQuery(id), null);
      if (!ius.isEmpty())
      {
        for (IInstallableUnit iu : ius)
        {
          if (firstVersion == null)
          {
            firstVersion = iu.getVersion();
          }
          else
          {
            if (list == null)
            {
              list = new LinkedList<Version>();
              versions.put(id, list);
            }

            list.add(iu.getVersion());
          }
        }
      }

      return firstVersion;
    }
  }

  /**
   * @author Eike Stepper
   */
  public interface CompareHandler<K>
  {
    public void handleAddition(K key, String value);

    public void handleRemoval(K key);
  }

  /**
   * @author Eike Stepper
   */
  private static final class IUPropertyKey
  {
    private static final int PRIME = 31;

    private final IInstallableUnit iu;

    private final String propertyKey;

    private final int hashCode;

    public IUPropertyKey(IInstallableUnit iu, String propertyKey)
    {
      this.iu = iu;
      this.propertyKey = propertyKey;
      hashCode = PRIME * (PRIME + iu.hashCode()) + propertyKey.hashCode();
    }

    public IInstallableUnit getInstallableUnit()
    {
      return iu;
    }

    public String getPropertyKey()
    {
      return propertyKey;
    }

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

    @Override
    public boolean equals(Object obj)
    {
      if (this == obj)
      {
        return true;
      }

      IUPropertyKey other = (IUPropertyKey)obj;
      if (!iu.equals(other.iu))
      {
        return false;
      }

      if (!propertyKey.equals(other.propertyKey))
      {
        return false;
      }

      return true;
    }

    @Override
    public String toString()
    {
      return iu.toString() + " / " + propertyKey;
    }
  }

  /**
   * @author Ed Merks
   */
  private static final class RepositoryLoader extends WorkerPool<RepositoryLoader, URI, RepositoryLoader.Worker>
  {
    private final IMetadataRepositoryManager manager;

    private final URI[] uris;

    private final List<IMetadataRepository> metadataRepositories = Collections.synchronizedList(new ArrayList<IMetadataRepository>());

    private ProvisionException exception;

    public RepositoryLoader(IMetadataRepositoryManager manager, URI... uris)
    {
      this.manager = manager;
      this.uris = uris;
    }

    public void begin(IProgressMonitor monitor)
    {
      try
      {
        monitor.beginTask("", uris.length + 1);
        monitor.worked(1);
        begin("Load Repositories", monitor);
      }
      finally
      {
        monitor.done();
      }
    }

    public ProvisionException getException()
    {
      return exception;
    }

    @Override
    protected void run(String taskName, IProgressMonitor monitor)
    {
      perform(uris);
    }

    @Override
    protected Worker createWorker(URI key, int workerID, boolean secondary)
    {
      return new Worker("Repository loader for " + key, this, key, workerID, secondary);
    }

    /**
     * @author Ed Merks
     */
    private static class Worker extends WorkerPool.Worker<URI, RepositoryLoader>
    {
      public Worker(String name, RepositoryLoader workPool, URI key, int id, boolean secondary)
      {
        super(name, workPool, key, id, secondary);
      }

      @Override
      protected IStatus perform(IProgressMonitor monitor)
      {
        RepositoryLoader workPool = getWorkPool();
        if (workPool.isCanceled())
        {
          return Status.CANCEL_STATUS;
        }

        try
        {
          IMetadataRepository metadataRepository = workPool.manager.loadRepository(getKey(), new SubProgressMonitor(monitor, 1));
          workPool.metadataRepositories.add(metadataRepository);
          return Status.OK_STATUS;
        }
        catch (ProvisionException ex)
        {
          workPool.cancel();
          workPool.exception = ex;
          return P2CorePlugin.INSTANCE.getStatus(ex);
        }
        catch (OperationCanceledException ex)
        {
          return Status.CANCEL_STATUS;
        }
      }
    }
  }
}
