/*
 * Copyright (c) 2014-2016 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.util.CollectionUtil;
import org.eclipse.oomph.util.IOUtil;
import org.eclipse.oomph.util.OfflineMode;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.oomph.util.ReflectUtil.ReflectionException;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
import org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager;
import org.eclipse.equinox.internal.p2.artifact.repository.MirrorSelector;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
import org.eclipse.equinox.internal.p2.engine.CommitOperationEvent;
import org.eclipse.equinox.internal.p2.engine.RollbackOperationEvent;
import org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager;
import org.eclipse.equinox.internal.p2.repository.DownloadStatus;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager;
import org.eclipse.equinox.internal.p2.repository.helpers.LocationProperties;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.SynchronousProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.IAgentLocation;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.osgi.util.NLS;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Eike Stepper
 */
@SuppressWarnings("restriction")
public class CachingRepositoryManager<T>
{
  public static final String BOGUS_SCHEME = "bogus";

  private static final Method METHOD_checkValidLocation = ReflectUtil.getMethod(AbstractRepositoryManager.class, "checkValidLocation", URI.class);

  private static final Method METHOD_enterLoad = ReflectUtil.getMethod(AbstractRepositoryManager.class, "enterLoad", URI.class, IProgressMonitor.class);

  private static final Method METHOD_basicGetRepository = ReflectUtil.getMethod(AbstractRepositoryManager.class, "basicGetRepository", URI.class);

  private static final Method METHOD_fail = ReflectUtil.getMethod(AbstractRepositoryManager.class, "fail", URI.class, int.class);

  private static final Method METHOD_addRepository1 = ReflectUtil.getMethod(AbstractRepositoryManager.class, "addRepository", URI.class, boolean.class,
      boolean.class);

  private static final Method METHOD_loadIndexFile = ReflectUtil.getMethod(AbstractRepositoryManager.class, "loadIndexFile", URI.class, IProgressMonitor.class);

  private static final Method METHOD_getPreferredRepositorySearchOrder = ReflectUtil.getMethod(AbstractRepositoryManager.class,
      "getPreferredRepositorySearchOrder", LocationProperties.class);

  private static final Method METHOD_getAllSuffixes = ReflectUtil.getMethod(AbstractRepositoryManager.class, "getAllSuffixes");

  private static final Method METHOD_loadRepository = ReflectUtil.getMethod(AbstractRepositoryManager.class, "loadRepository", URI.class, String.class,
      String.class, int.class, SubMonitor.class);

  private static final Method METHOD_addRepository2 = ReflectUtil.getMethod(AbstractRepositoryManager.class, "addRepository", IRepository.class, boolean.class,
      String.class);

  private static final Method METHOD_removeRepository = ReflectUtil.getMethod(AbstractRepositoryManager.class, "removeRepository", URI.class, boolean.class);

  private static final Method METHOD_exitLoad = ReflectUtil.getMethod(AbstractRepositoryManager.class, "exitLoad", URI.class);

  private static final Method METHOD_broadcastChangeEvent = ReflectUtil.getMethod(AbstractRepositoryManager.class, "broadcastChangeEvent", URI.class, int.class,
      int.class, boolean.class);

  private static final String PROPERTY_VERSION = "version";

  private static final String PROP_BETTER_MIRROR_SELECTION = "oomph.p2.mirror";

  private static boolean betterMirrorSelection;

  private final AbstractRepositoryManager<T> delegate;

  private final int repositoryType;

  private final CachingTransport transport;

  public CachingRepositoryManager(AbstractRepositoryManager<T> delegate, int repositoryType, CachingTransport transport)
  {
    this.delegate = delegate;

    IAgentLocation agentLocation = ReflectUtil.getValue("agentLocation", delegate);
    if (agentLocation != null)
    {
      URI rootLocation = agentLocation.getRootLocation();
      if (rootLocation != null)
      {
        if (!IOUtil.canWriteFolder(new File(rootLocation.getPath())))
        {
          ReflectUtil.setValue("agentLocation", delegate, null);
        }
      }
    }

    this.repositoryType = repositoryType;

    if (transport == null)
    {
      Object t = delegate.getAgent().getService(Transport.SERVICE_NAME);
      if (t instanceof CachingTransport)
      {
        transport = (CachingTransport)t;
      }
    }

    this.transport = transport;
  }

  public CachingTransport getTransport()
  {
    return transport;
  }

  public IRepository<T> loadRepository(URI location, IProgressMonitor monitor, String type, int flags) throws ProvisionException
  {
    checkValidLocation(location);
    SubMonitor sub = SubMonitor.convert(monitor, 100);
    boolean added = false;
    IRepository<T> result = null;

    CachingTransport.startLoadingRepository(location);

    try
    {
      enterLoad(location, sub.newChild(5));

      try
      {
        result = basicGetRepository(location);
        if (result != null)
        {
          return result;
        }

        // Add the repository first so that it will be enabled, but don't send add event until after the load.
        added = addRepository(location, true, false);

        LocationProperties indexFile = loadIndexFile(location, sub.newChild(15));
        String[] preferredOrder = getPreferredRepositorySearchOrder(indexFile);
        String[] allSuffixes = getAllSuffixes();
        String[] suffixes = sortSuffixes(allSuffixes, preferredOrder);

        sub = SubMonitor.convert(sub, NLS.bind("Adding repository {0}", location), suffixes.length * 100);
        ProvisionException failure = null;

        try
        {
          for (int i = 0; i < suffixes.length; i++)
          {
            if (sub.isCanceled())
            {
              throw new OperationCanceledException();
            }

            try
            {
              result = loadRepository(location, suffixes[i], type, flags, sub.newChild(100));
            }
            catch (ProvisionException e)
            {
              if (!(e.getStatus().getException() instanceof FileNotFoundException))
              {
                failure = e;
                break;
              }
            }

            if (result != null)
            {
              addRepository(result, false, suffixes[i]);
              cacheIndexFile(location, suffixes[i]);
              break;
            }
          }
        }
        finally
        {
          sub.done();
        }

        if (result == null)
        {
          // If we just added the repository, remove it because it cannot be loaded.
          if (added)
          {
            removeRepository(location, false);
          }

          // Eagerly cleanup missing system repositories.
          if (Boolean.parseBoolean(delegate.getRepositoryProperty(location, IRepository.PROP_SYSTEM)))
          {
            delegate.removeRepository(location);
          }

          if (failure != null)
          {
            throw failure;
          }

          fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
        }
      }
      finally
      {
        exitLoad(location);
      }
    }
    finally
    {
      CachingTransport.stopLoadingRepository();
    }

    // Broadcast the add event after releasing lock.
    if (added)
    {
      broadcastChangeEvent(location, repositoryType, RepositoryEvent.ADDED, true);
    }

    return result;
  }

  private File getCachedIndexFile(URI location)
  {
    try
    {
      String path = location.toString();
      if (!path.endsWith("/"))
      {
        path += "/";
      }

      return transport.getCacheFile(new URI(path + "p2.index"));
    }
    catch (URISyntaxException ex)
    {
      // Can't happen.
      throw new RuntimeException(ex);
    }
  }

  private void cacheIndexFile(URI location, String suffix)
  {
    if ("file".equals(location.getScheme()))
    {
      return;
    }

    File cachedIndexFile = getCachedIndexFile(location);

    Map<String, String> properties = PropertiesUtil.getProperties(cachedIndexFile);
    if (!properties.containsKey(PROPERTY_VERSION))
    {
      properties.put(PROPERTY_VERSION, "1");
    }

    if (repositoryType == IRepository.TYPE_METADATA)
    {
      properties.put("metadata.repository.factory.order", suffix);
    }
    else
    {
      properties.put("artifact.repository.factory.order", suffix);
    }

    // Cleanup; can be removed at some point in the future...
    properties.remove("generated");

    PropertiesUtil.saveProperties(cachedIndexFile, properties, false);
  }

  private URI checkValidLocation(URI location)
  {
    return (URI)ReflectUtil.invokeMethod(METHOD_checkValidLocation, delegate, location);
  }

  private void enterLoad(URI location, IProgressMonitor monitor)
  {
    ReflectUtil.invokeMethod(METHOD_enterLoad, delegate, location, monitor);
  }

  @SuppressWarnings("unchecked")
  protected IRepository<T> basicGetRepository(URI location)
  {
    return (IRepository<T>)ReflectUtil.invokeMethod(METHOD_basicGetRepository, delegate, location);
  }

  // private boolean checkNotFound(URI location)
  // {
  // return (Boolean)ReflectUtil.invokeMethod(METHOD_checkNotFound, delegate, location);
  // }
  //
  // private void rememberNotFound(URI location)
  // {
  // ReflectUtil.invokeMethod(METHOD_rememberNotFound, delegate, location);
  // }

  private void fail(URI location, int code) throws ProvisionException
  {
    try
    {
      ReflectUtil.invokeMethod(METHOD_fail, delegate, location, code);
    }
    catch (ReflectionException ex)
    {
      Throwable cause = ex.getCause();
      if (cause instanceof ProvisionException)
      {
        throw (ProvisionException)cause;
      }

      throw ex;
    }
  }

  private boolean addRepository(URI location, boolean isEnabled, boolean signalAdd)
  {
    return (Boolean)ReflectUtil.invokeMethod(METHOD_addRepository1, delegate, location, isEnabled, signalAdd);
  }

  private LocationProperties loadIndexFile(URI location, IProgressMonitor monitor)
  {
    return (LocationProperties)ReflectUtil.invokeMethod(METHOD_loadIndexFile, delegate, location, monitor);
  }

  protected String[] getPreferredRepositorySearchOrder(LocationProperties properties)
  {
    return (String[])ReflectUtil.invokeMethod(METHOD_getPreferredRepositorySearchOrder, delegate, properties);
  }

  protected String[] getAllSuffixes()
  {
    return (String[])ReflectUtil.invokeMethod(METHOD_getAllSuffixes, delegate);
  }

  private String[] sortSuffixes(String[] allSuffixes, String[] preferredOrder)
  {
    List<String> suffixes = new ArrayList<String>(Arrays.asList(allSuffixes));

    for (int i = preferredOrder.length - 1; i >= 0; --i)
    {
      String suffix = preferredOrder[i].trim();
      if (!LocationProperties.END.equals(suffix))
      {
        suffixes.remove(suffix);
        suffixes.add(0, suffix);
      }
    }

    return suffixes.toArray(new String[suffixes.size()]);
  }

  @SuppressWarnings("unchecked")
  private IRepository<T> loadRepository(URI location, String suffix, String type, int flags, SubMonitor monitor) throws ProvisionException
  {
    try
    {
      return (IRepository<T>)ReflectUtil.invokeMethod(METHOD_loadRepository, delegate, location, suffix, type, flags, monitor);
    }
    catch (ReflectionException ex)
    {
      Throwable cause = ex.getCause();
      if (cause instanceof ProvisionException)
      {
        throw (ProvisionException)cause;
      }

      throw ex;
    }
  }

  protected void addRepository(IRepository<T> repository, boolean signalAdd, String suffix)
  {
    ReflectUtil.invokeMethod(METHOD_addRepository2, delegate, repository, signalAdd, suffix);
  }

  private boolean removeRepository(URI toRemove, boolean signalRemove)
  {
    return (Boolean)ReflectUtil.invokeMethod(METHOD_removeRepository, delegate, toRemove, signalRemove);
  }

  private void exitLoad(URI location)
  {
    ReflectUtil.invokeMethod(METHOD_exitLoad, delegate, location);
  }

  private void broadcastChangeEvent(URI location, int repositoryType, int kind, boolean isEnabled)
  {
    ReflectUtil.invokeMethod(METHOD_broadcastChangeEvent, delegate, location, repositoryType, kind, isEnabled);
  }

  public static boolean isBetterMirrorSelection()
  {
    return betterMirrorSelection;
  }

  public static boolean enableBetterMirrorSelection()
  {
    boolean originalBetterMirrorSelection = betterMirrorSelection;
    setBetterMirrorSelection(!"false".equals(PropertiesUtil.getProperty(PROP_BETTER_MIRROR_SELECTION)));
    return originalBetterMirrorSelection;
  }

  public static void setBetterMirrorSelection(boolean betterMirrorSelection)
  {
    CachingRepositoryManager.betterMirrorSelection = betterMirrorSelection;
  }

  /**
   * @author Eike Stepper
   */
  public static class Metadata extends MetadataRepositoryManager
  {
    private final CachingRepositoryManager<IInstallableUnit> loader;

    public Metadata(IProvisioningAgent agent, CachingTransport transport)
    {
      super(agent);
      loader = new CachingRepositoryManager<IInstallableUnit>(this, IRepository.TYPE_METADATA, transport);
    }

    @Override
    protected IRepository<IInstallableUnit> loadRepository(URI location, IProgressMonitor monitor, String type, int flags) throws ProvisionException
    {
      return loader.loadRepository(location, monitor, type, flags);
    }

    @Override
    public URI[] getKnownRepositories(int flags)
    {
      return filter(super.getKnownRepositories(flags));
    }

    /**
     * Work-around for bug 483286.
     */
    @Override
    public void flushCache()
    {
      synchronized (repositoryLock)
      {
        if (repositories != null)
        {
          super.flushCache();
        }
      }
    }

    static URI[] filter(URI[] uris)
    {
      List<URI> result = new ArrayList<URI>(uris.length);
      for (URI uri : uris)
      {
        try
        {
          if (!"file".equalsIgnoreCase(uri.getScheme()) || new File(uri).isDirectory())
          {
            result.add(uri);
          }
        }
        catch (IllegalArgumentException ex)
        {
          //$FALL-THROUGH$
        }
      }

      return result.toArray(new URI[result.size()]);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static class Artifact extends ArtifactRepositoryManager
  {
    private static final String GLOBAL_MAX_THREADS = Activator.getContext().getProperty(SimpleArtifactRepository.PROP_MAX_THREADS);

    private final CachingRepositoryManager<IArtifactKey> loader;

    public Artifact(IProvisioningAgent agent, CachingTransport transport)
    {
      super(agent);
      loader = new CachingRepositoryManager<IArtifactKey>(this, IRepository.TYPE_ARTIFACT, transport);
    }

    @Override
    protected IRepository<IArtifactKey> loadRepository(URI location, IProgressMonitor monitor, String type, int flags) throws ProvisionException
    {
      // Inspect the repository if better mirror selection is enabled,
      // the repository is simple
      // and the repository not modifiable, i.e., if it's not a local file-based repository.
      IRepository<IArtifactKey> result = loader.loadRepository(location, monitor, type, flags);
      if (isBetterMirrorSelection() && result instanceof SimpleArtifactRepository && !result.isModifiable())
      {
        // There should always be an event bus.
        IProvisioningEventBus eventBus = (IProvisioningEventBus)getAgent().getService(IProvisioningEventBus.SERVICE_NAME);
        if (eventBus != null)
        {
          // Create our improved mirror selector and reflectively set it to be the one used by this repository.
          final BetterMirrorSelector mirrorSelector = new BetterMirrorSelector(result, loader.getTransport(), eventBus);
          ReflectUtil.setValue("mirrors", result, mirrorSelector);

          // Because of the poor implementation in org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository.getMaximumThreads()
          // which was reported in https://bugs.eclipse.org/bugs/show_bug.cgi?id=471861 but is not yet fixed,
          // we work the around the problem by setting the global PROP_MAX_THREADS into the repository properties.
          if (GLOBAL_MAX_THREADS != null)
          {
            Map<String, String> properties = ReflectUtil.getValue("properties", result);
            Map<String, String> specializedProperties = new OrderedProperties()
            {
              @Override
              public Set<java.util.Map.Entry<String, String>> entrySet()
              {
                if (!OfflineMode.isEnabled())
                {
                  // If the request for the entry set occurs when p2 is determining the maximum number of threads allowed by the repository...
                  StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
                  if (stackTrace.length > 5 && "getMaximumThreads".equals(stackTrace[5].getMethodName()))
                  {
                    // If the repository itself doesn't restrict the maximum number of threads...
                    String respositoryMaxThreads = get(SimpleArtifactRepository.PROP_MAX_THREADS);
                    if (respositoryMaxThreads == null)
                    {
                      // Initialize our specialized mirror selector.
                      mirrorSelector.initMirrorActivities(new NullProgressMonitor());

                      // If there is no list of mirrors, allow 10 threads, otherwise, allow 10 threads per mirror or the global maximum, whichever is less.
                      // Save that value as if it were a property in the repository.
                      BetterMirrorSelector.MirrorActivity[] mirrorActivities = mirrorSelector.mirrorActivities;
                      int maxThreads = mirrorActivities.length <= 1 ? 10 : Math.min(mirrorActivities.length * 10, Integer.parseInt(GLOBAL_MAX_THREADS));
                      put(SimpleArtifactRepository.PROP_MAX_THREADS, Integer.toString(maxThreads));
                    }
                  }
                }

                return super.entrySet();
              }
            };

            // Copy over the properties and insert our specialized map reflective into the field of the base class.
            specializedProperties.putAll(properties);
            ReflectUtil.setValue("properties", result, specializedProperties);
          }
        }
      }

      return result;
    }

    @Override
    public URI[] getKnownRepositories(int flags)
    {
      return Metadata.filter(super.getKnownRepositories(flags));
    }

    /**
     * Work-around for bug 483286.
     */
    @Override
    public void flushCache()
    {
      synchronized (repositoryLock)
      {
        if (repositories != null)
        {
          super.flushCache();
        }
      }
    }

    /**
     * @author Eike Stepper
     * @author Ed Merks
     */
    static final class BetterMirrorSelector extends MirrorSelector implements SynchronousProvisioningListener
    {
      /**
       * The main artifact repository.
       */
      private final URI repositoryURI;

      /**
       * The event bus to which this selector listens.
       */
      private final IProvisioningEventBus eventBus;

      /**
       * A map from mirror URI to the artifact activity for that mirror.
       */
      private final Map<URI, ArtifactActivity> artifactActivities = Collections.synchronizedMap(new HashMap<URI, ArtifactActivity>());

      /**
       * The phase in which we are using mirrors.
       * During the initial phase, each mirror is probed to measure performance.
       * Subsequently only the faster mirrors are used.
       */
      private int phase = 1;

      /**
       * The per-mirror activities being managed.
       */
      private MirrorActivity[] mirrorActivities;

      public BetterMirrorSelector(IRepository<?> repository, Transport transport, IProvisioningEventBus eventBus)
      {
        super(repository, transport);
        this.eventBus = eventBus;
        repositoryURI = getBaseURI();
      }

      public void notify(EventObject event)
      {
        // If we have mirror activities.
        if (mirrorActivities != null)
        {
          // If it's a download event.
          if (event instanceof DownloadArtifactEvent)
          {
            // Get the corresponding artifact activity for this event, if there is one..
            DownloadArtifactEvent downloadArtifactEvent = (DownloadArtifactEvent)event;
            URI artifactURI = downloadArtifactEvent.getArtifactURI();
            ArtifactActivity artifactActivity = artifactActivities.get(artifactURI);
            if (artifactActivity != null)
            {
              // Get the corresponding overall mirror activity.
              MirrorActivity mirrorActivity = artifactActivity.getMirrorActivity();
              if (downloadArtifactEvent.isCompleted())
              {
                // If the download is completed, reduce the usage count of this mirror.
                mirrorActivity.decrementUsage();

                // Determine if it was successful or not.
                IStatus status = downloadArtifactEvent.getStatus();
                if (status.isOK())
                {
                  // Increment the success count of this mirror.
                  mirrorActivity.incrementSuccess();

                  // Record the overall end-to-end speed based or course on the overall time for the download the start and complete along with the number of
                  // bytes.
                  DownloadStatus downloadStatus = (DownloadStatus)status;
                  long fileSize = downloadStatus.getFileSize();
                  artifactActivity.setSize(fileSize);
                  mirrorActivity.setSpeed(artifactActivity.getSpeed());
                }
                else
                {
                  // There was a failure.
                  mirrorActivity.incrementFailure();

                  // So no bytes were successfully downloaded.
                  artifactActivity.setSize(0);

                  // This will reduce the average speed of the mirror in half, quickly dropping it from consideration for use.
                  mirrorActivity.setSpeed(0);
                }
              }
              else
              {
                // If the download is started, increment the usage count of the mirror.
                mirrorActivity.incrementUsage();

                // Record the point in time at which this activity started.
                artifactActivity.setStart();
              }
            }
          }
          else if (event instanceof CommitOperationEvent || event instanceof RollbackOperationEvent)
          {
            // If we complete or we roll back, we remove this as a listener.
            if (eventBus != null)
            {
              eventBus.removeListener(this);
            }

            // And reset our state to the intial state for subsequent reuse.
            mirrorActivities = null;
            artifactActivities.clear();
            phase = 1;
          }
        }
      }

      @Override
      public synchronized URI getMirrorLocation(URI inputLocation, IProgressMonitor monitor)
      {
        // If we don't know the repository URI, we can't request mirrors.
        Assert.isNotNull(inputLocation);
        if (repositoryURI == null)
        {
          return inputLocation;
        }

        // Determine the relative location of the download with respect to the repository.
        URI relativeLocation = repositoryURI.relativize(inputLocation);
        if (relativeLocation == null || relativeLocation.isAbsolute())
        {
          // If it's not relative, we just use the given URI.
          return inputLocation;
        }

        // Initialize the mirrors with a mirror request to populate the list.
        initMirrorActivities(monitor);

        // Select the mirror to be used for the artifact activity.
        MirrorActivity selectedMirror = selectMirror();
        if (selectedMirror == null)
        {
          // If there isn't one, we must use the given input.
          return inputLocation;
        }

        String location = selectedMirror.getLocation();
        try
        {
          // Determine the location within the mirror, create a new artifact activity for it, and see if there was previous such an activity.
          URI artifactURI = new URI(location + relativeLocation.getPath());
          ArtifactActivity newActivity = new ArtifactActivity(selectedMirror);
          ArtifactActivity previousActivity = artifactActivities.put(artifactURI, newActivity);
          if (previousActivity != null)
          {
            if (!newActivity.retry(previousActivity))
            {
              // Return a bogus URI that will refuse to try this artifactURI from this mirror again.
              return new URI(BOGUS_SCHEME + ":" + artifactURI);
            }

            // We don't expect to have repeated requests for the same artifact.
            // But this does happen if it's a .pack.gz produced by a version of Java newer than the version of Java being used by this process.
            monitor.subTask("Repeated attempts to download " + artifactURI + " probably because it can't be processed");
          }

          // Use this location in the mirror instead of the original URI.
          return artifactURI;
        }
        catch (URISyntaxException e)
        {
          log("Unable to make location " + inputLocation + " relative to mirror " + location, e);
        }

        // If all else fails, we must use the original URI.
        return inputLocation;
      }

      private MirrorActivity selectMirror()
      {
        // If we don't have mirrors, we can't select one.
        if (mirrorActivities.length == 0)
        {
          return null;
        }

        if (phase == 1)
        {
          // During phase one, we try to probe each mirror once to measure speed.
          for (MirrorActivity mirrorActivity : mirrorActivities)
          {
            if (!mirrorActivity.isProbed())
            {
              mirrorActivity.setProbed();
              return mirrorActivity;
            }
          }

          // Once all mirrors are probed, we enter phase two.
          phase = 2;
        }

        // We sort the mirrors based on performance, favoring faster mirrors of course.
        sort();

        for (MirrorActivity mirrorActivity : mirrorActivities)
        {
          // We try to limit the number of simultaneous activities per mirror to avoid overloading any one mirror.
          int MAX_ACTIVITY_PER_HOST = 4;
          int usages = mirrorActivity.getUsages();
          if (usages < MAX_ACTIVITY_PER_HOST)
          {
            // Return the fasted one that's not so busy.
            return mirrorActivity;
          }
        }

        // Find the least used mirror in the first half of the available mirrors.
        MirrorActivity leastUsedMirror = null;
        for (MirrorActivity mirrorActivity : mirrorActivities)
        {
          int usages = mirrorActivity.getUsages();
          if (leastUsedMirror == null || leastUsedMirror.getUsages() > usages)
          {
            leastUsedMirror = mirrorActivity;
          }
        }

        return leastUsedMirror;
      }

      public List<String> getStats()
      {
        // Compute statistics for the mirror speeds.
        List<String> result = new ArrayList<String>();
        if (mirrorActivities != null)
        {
          // We'll create new mirror activities to summarize the result.
          MirrorActivity[] summaryMirrorActivities = new MirrorActivity[mirrorActivities.length];

          for (int i = 0; i < mirrorActivities.length; ++i)
          {
            MirrorActivity mirrorActivity = mirrorActivities[i];
            MirrorActivity summaryMirrorActivity = summaryMirrorActivities[i] = new MirrorActivity(mirrorActivity.location);
            for (int j = 0; j < mirrorActivity.getFailures(); ++j)
            {
              // Record the number of failures.
              summaryMirrorActivity.incrementFailure();
            }

            // Compute the total number of bytes and the total time taken to download them for all the artifact activities.
            long totalSize = 0;
            long totalDuration = 0;
            for (ArtifactActivity artifactActivity : artifactActivities.values())
            {
              if (artifactActivity.getMirrorActivity() == mirrorActivity)
              {
                summaryMirrorActivity.incrementSuccess();
                totalSize += artifactActivity.getSize();
                totalDuration += artifactActivity.getDuration();
              }
            }

            if (totalSize != 0)
            {
              // Record this as the overall result of the mirror activity.
              summaryMirrorActivity.setSpeed(1000 * totalSize / totalDuration);
            }
          }

          // Replace with the summary.
          mirrorActivities = summaryMirrorActivities;

          // Sort them again.
          sort();

          // Add only the ones that actually were used to the final result.
          for (MirrorActivity mirrorActivity : mirrorActivities)
          {
            if (mirrorActivity.getSuccesses() + mirrorActivity.getFailures() > 0)
            {
              result.add(getStats(mirrorActivity));
            }
          }
        }

        return result;
      }

      private String getStats(MirrorActivity mirrorActivity)
      {
        // Compute a nice string representation for the mirror activity.
        NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
        int successes = mirrorActivity.getSuccesses();
        int failures = mirrorActivity.getFailures();
        String message = "Mirrored " + successes + " artifacts from " + mirrorActivity.getLocation() + " at "
            + numberFormat.format(mirrorActivity.getSpeed() / 1000) + "kb/s";
        if (failures > 0)
        {
          message += " with " + failures + " failures";
        }

        return message;
      }

      private void sort()
      {
        // Compute a sorted map from the speed to the mirror activity with that speed.
        Map<Long, Set<MirrorActivity>> sortedMap = new TreeMap<Long, Set<MirrorActivity>>();
        for (MirrorActivity mirrorActivity : mirrorActivities)
        {
          long value = mirrorActivity.getSpeed();
          CollectionUtil.add(sortedMap, value, mirrorActivity);
        }

        // Flatten out the values of the map back into the array.
        int index = mirrorActivities.length;
        for (Set<MirrorActivity> acitivities : sortedMap.values())
        {
          for (MirrorActivity mirrorActivity : acitivities)
          {
            mirrorActivities[--index] = mirrorActivity;
          }
        }
      }

      private void initMirrorActivities(IProgressMonitor monitor)
      {
        // Do this only once.
        if (mirrorActivities == null)
        {
          // Delete to p2's implementation.
          Method method = ReflectUtil.getMethod(this, "initMirrors", IProgressMonitor.class);
          MirrorInfo[] mirrors = (MirrorInfo[])ReflectUtil.invokeMethod(method, this, monitor);
          if (mirrors == null)
          {
            mirrors = new MirrorInfo[0];
          }

          // Use only the first two thirds of the list.
          int limit = (mirrors.length + 2) / 3;
          if (limit == 0 && repositoryURI != null)
          {
            // Even if there are no mirrors treat it as a single mirror so that activities and performance can always be monitored.
            String locationString = repositoryURI.toString();
            if (!locationString.endsWith("/"))
            {
              locationString += Character.toString('/');
            }

            mirrorActivities = new MirrorActivity[] { new MirrorActivity(locationString) };
          }
          else
          {
            mirrorActivities = new MirrorActivity[limit];
            for (int i = 0; i < limit; i++)
            {
              // Convert the mirror info to our mirror activity representation.
              MirrorInfo mirrorInfo = mirrors[i];
              String locationString = getLocationString(mirrorInfo);
              MirrorActivity mirrorActivity = new MirrorActivity(locationString);
              mirrorActivities[i] = mirrorActivity;
            }
          }

          // Do ourselves as a listener.
          if (eventBus != null)
          {
            eventBus.addListener(this);
          }
        }
      }

      private URI getBaseURI()
      {
        return ReflectUtil.getValue("baseURI", this);
      }

      private static String getLocationString(MirrorInfo mirrorInfo)
      {
        return ReflectUtil.getValue("locationString", mirrorInfo);
      }

      private static void log(String message, Throwable exception)
      {
        LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, exception));
      }

      /**
       * @author Ed Merks
       */
      private static class ArtifactActivity
      {
        private final MirrorActivity mirrorActivity;

        private long start;

        private long end;

        private long size;

        private int retryCount;

        public ArtifactActivity(MirrorActivity mirrorActivity)
        {
          this.mirrorActivity = mirrorActivity;
        }

        public MirrorActivity getMirrorActivity()
        {
          return mirrorActivity;
        }

        public void setStart()
        {
          this.start = System.currentTimeMillis();
        }

        public void setSize(long size)
        {
          end = System.currentTimeMillis();
          this.size = size;
        }

        public long getDuration()
        {
          return end - start;
        }

        public long getSpeed()
        {
          return size * 1000 / (end - start);
        }

        public long getSize()
        {
          return size;
        }

        public boolean retry(ArtifactActivity previousArtifactActivity)
        {
          if (previousArtifactActivity != null)
          {
            retryCount = previousArtifactActivity.retryCount + 1;
          }

          return retryCount < 3;
        }

        @Override
        public String toString()
        {
          return "ArtifactActivity [start=" + start + ", end=" + end + ", size=" + size + ", duration=" + getDuration() + ", speed=" + getSpeed() + "]";
        }
      }

      /**
       * @author Ed Merks
       */
      private static class MirrorActivity
      {
        private final String location;

        private final AtomicInteger usages = new AtomicInteger();

        private final AtomicInteger successes = new AtomicInteger();

        private final AtomicInteger failures = new AtomicInteger();

        private final AtomicLong speed = new AtomicLong();

        private boolean probed;

        public MirrorActivity(String location)
        {
          this.location = location;
        }

        public String getLocation()
        {
          return location;
        }

        public boolean isProbed()
        {
          return probed;
        }

        public void setProbed()
        {
          probed = true;
        }

        public int getUsages()
        {
          return usages.get();
        }

        public void incrementUsage()
        {
          usages.incrementAndGet();
        }

        public void decrementUsage()
        {
          usages.decrementAndGet();
        }

        public int getSuccesses()
        {
          return successes.get();
        }

        public void incrementSuccess()
        {
          successes.incrementAndGet();
        }

        public int getFailures()
        {
          return failures.get();
        }

        public void incrementFailure()
        {
          failures.incrementAndGet();
        }

        public synchronized long getSpeed()
        {
          return speed.get();
        }

        public synchronized void setSpeed(long speed)
        {
          long currentSpeed = this.speed.get();
          if (currentSpeed == 0)
          {
            currentSpeed = speed;
          }
          else
          {
            currentSpeed = (currentSpeed + speed) / 2;
          }

          this.speed.set(currentSpeed);
        }

        @Override
        public String toString()
        {
          return "MirrorActivity [location=" + location + ", usages=" + usages.get() + ", successes=" + successes.get() + ", failures=" + failures.get()
              + ", speed=" + speed.get() + ", probed=" + probed + "]";
        }
      }
    }
  }
}
