/*
 * Copyright (c) 2014 Eike Stepper (Berlin, Germany) and others.
 * Copyright (c) 2014 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:
 *    Stefan Xenos - initial API and implementation
 *    Stefan Xenos - bug 174539 - add a 1-argument convert(...) method
 *    Stefan Xenos - bug 174040 - SubMonitor#convert doesn't always set task name
 *    Stefan Xenos - bug 206942 - updated javadoc to recommend better constants for infinite progress
 *    IBM Corporation - ongoing maintenance
 *    Eike Stepper - copied from org.eclipse.core.runtime.SubMonitor and enhanced as outlined in the JavaDoc below
 */
package org.eclipse.net4j.util.om.monitor;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;

/**
 * A {@link IProgressMonitorWithBlocking progress monitor} that uses a given amount of work ticks from a parent monitor.
 * This is intended as a safer, easier-to-use alternative to {@link SubProgressMonitor}.
 * <p>
 * Progress monitoring is generally quite invasive to the code that is monitored.
 * At the same time progress monitoring itself is typically very hard to implement correctly.
 * This class aims at reducing the invasiveness as much as possible while offering all the functionality needed
 * to do the job right.
 * <p>
 * The following aspects of this class help to keep the progress monitoring code short and nice and to avoid common monitoring mistakes:
 * <ul>
 * <li> It offers the full functionality of {@link org.eclipse.core.runtime.SubMonitor}, which already makes progress monitoring a lot easier.
 *      Refer to the {@link org.eclipse.core.runtime.SubMonitor} documentation or to this <a href="https://wiki.eclipse.org/Progress_Reporting">article</a> for details and examples.
 *
 * <li> In addition to the {@link SubMonitor#setWorkRemaining(int)} method it offers a {@link #skipped(int)} method, which redistributes the remaining work
 *      according to the last skipped {@link #worked(int)} or {@link #newChild(int)} call rather than on the sum of all subsequent calls.
 *
 * <li> It reduces the need to specify <code>work</code> arguments by using the default value {@link #DEFAULT_WORK 1} with the overloaded
 *      {@link #worked()}, {@link #skipped()} and {@link #newChild()} calls.
 *
 * <li> Basically all methods of this class can implicitely check for cancelation, thereby ensuring that the monitored code is always cancelable by the user
 *      without cluttering the code with repetitions of the following idiom:
 *      <pre>
if (monitor.isCanceled())
{
  throw new OperationCanceledException();
}
 *      </pre>
 *      For details about automatic cancelation detection refer to {@link #detectCancelation()}.
 *
 * <li> It is normally very challenging to find out how much time a program really spends in the different parts of the monitored methods or how often these
 *      parts get executed. Stepping through the program with a debugger obviously leads to distortion that renders the observations meaningless and adding
 *      extra code to measure a runtime scenario realisticly is not nice from a maintenance point of view.
 *      <p>
 *      As a solution to this problem this class offers the possibility to transparently instrument {@link SubMonitor} instances such that they automatically
 *      collect and report all kinds of statistics that may help to enhance the user experience. Sometimes it would even indicate to remove some progress monitoring
 *      because it turns out that almost no time is being spent in a particular part of the program. Another typical result from the analysis is the understanding of
 *      <i>one time effects</i> that might need special consideration.
 *      <p>
 *      For details about this <i>probing</i> mode refer to {@link ProbingSubMonitor}.
 * </ul>
 * <p>
 * The following example shows how to monitor progress while recursing through a tree of folders:
 * <pre>
public void recurse(IContainer container, IProgressMonitor monitor) throws Exception
{
  IResource[] members = container.members();

  SubMonitor progress = SubMonitor.convert(monitor, members.length).detectCancelation();
  progress.subTask(container.getFullPath().toString());

  for (IResource member : members)
  {
    if (member instanceof IContainer)
    {
      Thread.sleep(5);
      recurse((IContainer)member, progress.newChild());
    }
    else
    {
      progress.skipped();
    }
  }
}
 * </pre>
 *
 * @author Eike Stepper
 * @since 3.4
 */
public class SubMonitor implements IProgressMonitorWithBlocking
{
  /**
   * Minimum number of ticks to allocate when calling beginTask on an unknown IProgressMonitor.
   * Pick a number that is big enough such that, no matter where progress is being displayed,
   * the user would be unlikely to notice if progress were to be reported with higher accuracy.
   */
  private static final int MINIMUM_RESOLUTION = 1000;

  /**
   * The RootInfo holds information about the root progress monitor. A SubMonitor and
   * its active descendents share the same RootInfo.
   */
  // Can't be private because ProbingSubMonitor uses it.
  static final class RootInfo
  {
    private final IProgressMonitor root;

    /**
     * Remembers the last task name. Prevents us from setting the same task name multiple
     * times in a row.
     */
    private String taskName = null;

    /**
     * Remembers the last subtask name. Prevents the SubMonitor from setting the same
     * subtask string more than once in a row.
     */
    private String subTask = null;

    /**
     * Creates a RootInfo struct that delegates to the given progress
     * monitor.
     *
     * @param root progress monitor to delegate to
     */
    public RootInfo(IProgressMonitor root)
    {
      this.root = root;
    }

    public IProgressMonitor getRoot()
    {
      return root;
    }

    public boolean isCanceled()
    {
      return root.isCanceled();
    }

    public void setCanceled(boolean value)
    {
      root.setCanceled(value);
    }

    public void setTaskName(String taskName)
    {
      if (eq(taskName, this.taskName))
      {
        return;
      }
      this.taskName = taskName;
      root.setTaskName(taskName);
    }

    public void subTask(String name)
    {
      if (eq(subTask, name))
      {
        return;
      }

      subTask = name;
      root.subTask(name);
    }

    public void worked(int i)
    {
      root.worked(i);
    }

    public void clearBlocked()
    {
      if (root instanceof IProgressMonitorWithBlocking)
      {
        ((IProgressMonitorWithBlocking)root).clearBlocked();
      }
    }

    public void setBlocked(IStatus reason)
    {
      if (root instanceof IProgressMonitorWithBlocking)
      {
        ((IProgressMonitorWithBlocking)root).setBlocked(reason);
      }
    }

  }

  /**
   * Total number of ticks that this progress monitor is permitted to consume
   * from the root.
   */
  private int totalParent;

  /**
   * Number of ticks that this progress monitor has already reported in the root.
   */
  private int usedForParent = 0;

  /**
   * Number of ticks that have been consumed by this instance's children.
   */
  private double usedForChildren = 0.0;

  /**
   * Number of ticks allocated for this instance's children. This is the total number
   * of ticks that may be passed into worked(int) or newChild(int).
   */
  private int totalForChildren;

  /**
   * Children created by newChild will be completed automatically the next time
   * the parent progress monitor is touched. This points to the last incomplete child
   * created with newChild.
   */
  private IProgressMonitor lastSubMonitor = null;

  /**
   * Used to communicate with the root of this progress monitor tree
   */
  // Can't be private because ProbingSubMonitor reads from it.
  final RootInfo root;

  /**
   * A bitwise combination of the SUPPRESS_* flags.
   */
  // Can't be final because detectCancelation() writes to it.
  // Can't be private because ProbingSubMonitor reads from it.
  int flags;

  public static final int DEFAULT_WORK = 1;

  /**
   * May be passed as a flag to newChild. Indicates that the calls
   * to subTask on the child should be ignored. Without this flag,
   * calling subTask on the child will result in a call to subTask
   * on its parent.
   */
  public static final int SUPPRESS_SUBTASK = 0x0001;

  /**
   * May be passed as a flag to newChild. Indicates that strings
   * passed into beginTask should be ignored. If this flag is
   * specified, then the progress monitor instance will accept null
   * as the first argument to beginTask. Without this flag, any
   * string passed to beginTask will result in a call to
   * setTaskName on the parent.
   */
  public static final int SUPPRESS_BEGINTASK = 0x0002;

  /**
   * May be passed as a flag to newChild. Indicates that strings
   * passed into setTaskName should be ignored. If this string
   * is omitted, then a call to setTaskName on the child will
   * result in a call to setTaskName on the parent.
   */
  public static final int SUPPRESS_SETTASKNAME = 0x0004;

  /**
   * May be passed as a flag to newChild. Indicates that strings
   * passed to setTaskName, subTask, and beginTask should all be ignored.
   */
  public static final int SUPPRESS_ALL_LABELS = SUPPRESS_SETTASKNAME | SUPPRESS_BEGINTASK | SUPPRESS_SUBTASK;

  /**
   * May be passed as a flag to newChild. Indicates that strings
   * passed to setTaskName, subTask, and beginTask should all be propagated
   * to the parent.
   */
  public static final int SUPPRESS_NONE = 0;

  private static final int DETECT_CANCELATION = 0x0008;

  /**
   * Creates a new SubMonitor that will report its progress via
   * the given RootInfo.
   * @param rootInfo the root of this progress monitor tree
   * @param totalWork total work to perform on the given progress monitor
   * @param availableToChildren number of ticks allocated for this instance's children
   * @param flags a bitwise combination of the SUPPRESS_* constants
   */
  SubMonitor(RootInfo rootInfo, int totalWork, int availableToChildren, int flags)
  {
    root = rootInfo;
    totalParent = totalWork > 0 ? totalWork : 0;
    totalForChildren = availableToChildren;
    this.flags = flags;
  }

  SubMonitor createSubMonitor(RootInfo rootInfo, int totalWork, int availableToChildren, int flags)
  {
    // ProbingSubMonitor overwrites to create special sub monitors for probing and reporting purposes.
    return new SubMonitor(rootInfo, totalWork, availableToChildren, flags);
  }

  void adjustLocation()
  {
    // Do nothing here.
    // ProbingSubMonitor overwrites for probing and reporting purposes.
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is
   * not necessary to call done() on the result, but the caller is responsible for calling
   * done() on the argument. Calls beginTask on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
   * as a new instance of <code>NullProgressMonitor</code>.
   * @return a SubMonitor instance that adapts the argument
   */
  public static SubMonitor convert(IProgressMonitor monitor)
  {
    return convert(monitor, "", 0, ProbingMode.DEFAULT); //$NON-NLS-1$
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
   * with the given number of ticks. It is not necessary to call done() on the result,
   * but the caller is responsible for calling done() on the argument. Calls beginTask
   * on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
   * as a new instance of <code>NullProgressMonitor</code>.
   * @param work number of ticks that will be available in the resulting monitor
   * @return a SubMonitor instance that adapts the argument
   */
  public static SubMonitor convert(IProgressMonitor monitor, int work)
  {
    return convert(monitor, "", work, ProbingMode.DEFAULT); //$NON-NLS-1$
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
   * with the given number of ticks. It is not necessary to call done() on the result,
   * but the caller is responsible for calling done() on the argument. Calls beginTask
   * on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor to convert into a SubMonitor instance or null. If given a null argument,
   * the resulting SubMonitor will not report its progress anywhere.
   * @param taskName user readable name to pass to monitor.beginTask. Never null.
   * @param work initial number of ticks to allocate for children of the SubMonitor
   * @return a new SubMonitor instance that is a child of the given monitor
   */
  public static SubMonitor convert(IProgressMonitor monitor, String taskName, int work)
  {
    return convert(monitor, taskName, work, ProbingMode.DEFAULT);
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is
   * not necessary to call done() on the result, but the caller is responsible for calling
   * done() on the argument. Calls beginTask on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
   * as a new instance of <code>NullProgressMonitor</code>.
   * @return a SubMonitor instance that adapts the argument
   */
  public static SubMonitor convert(IProgressMonitor monitor, ProbingMode probingMode)
  {
    return convert(monitor, "", 0, probingMode); //$NON-NLS-1$
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
   * with the given number of ticks. It is not necessary to call done() on the result,
   * but the caller is responsible for calling done() on the argument. Calls beginTask
   * on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
   * as a new instance of <code>NullProgressMonitor</code>.
   * @param work number of ticks that will be available in the resulting monitor
   * @return a SubMonitor instance that adapts the argument
   */
  public static SubMonitor convert(IProgressMonitor monitor, int work, ProbingMode probingMode)
  {
    return convert(monitor, "", work, probingMode); //$NON-NLS-1$
  }

  /**
   * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
   * with the given number of ticks. It is not necessary to call done() on the result,
   * but the caller is responsible for calling done() on the argument. Calls beginTask
   * on the argument.</p>
   *
   * <p>This method should generally be called at the beginning of a method that accepts
   * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
   *
   * @param monitor to convert into a SubMonitor instance or null. If given a null argument,
   * the resulting SubMonitor will not report its progress anywhere.
   * @param taskName user readable name to pass to monitor.beginTask. Never null.
   * @param work initial number of ticks to allocate for children of the SubMonitor
   * @return a new SubMonitor instance that is a child of the given monitor
   */
  public static SubMonitor convert(IProgressMonitor monitor, String taskName, int work, ProbingMode probingMode)
  {
    if (monitor == null)
    {
      monitor = new NullProgressMonitor();
    }

    // Optimization: if the given monitor already a SubMonitor, no conversion is necessary
    if (monitor instanceof SubMonitor)
    {
      SubMonitor subMonitor = (SubMonitor)monitor;
      subMonitor.beginTask(taskName, work);
      subMonitor.adjustLocation();
      return subMonitor;
    }

    monitor.beginTask(taskName, MINIMUM_RESOLUTION);
    if (probingMode == ProbingMode.OFF)
    {
      return new SubMonitor(new RootInfo(monitor), MINIMUM_RESOLUTION, work, SUPPRESS_NONE);
    }

    return createProbingSubMonitor(monitor, work, probingMode == ProbingMode.FULL);
  }

  /**
   * Helps to avoid unnecessary loading of the {@link ProbingProgress} class, which forks a monitoring thread.
   */
  private static SubMonitor createProbingSubMonitor(IProgressMonitor monitor, int availableToChildren, boolean full)
  {
    ProbingSubMonitor parent = monitor instanceof ProbingSubMonitor ? (ProbingSubMonitor)monitor : null;
    return new ProbingSubMonitor(parent, new RootInfo(monitor), MINIMUM_RESOLUTION, availableToChildren, SUPPRESS_NONE,
        full);
  }

  public final SubMonitor detectCancelation()
  {
    return detectCancelation(true);
  }

  public final SubMonitor detectCancelation(boolean on)
  {
    if (on)
    {
      flags |= DETECT_CANCELATION;
    }
    else
    {
      flags &= ~DETECT_CANCELATION;
    }

    return this;
  }

  private void checkCancelation()
  {
    if ((flags & DETECT_CANCELATION) != 0 && isCanceled())
    {
      throw new OperationCanceledException();
    }
  }

  /**
   * <p>Sets the work remaining for this SubMonitor instance. This is the total number
   * of ticks that may be reported by all subsequent calls to worked(int), newChild(int), etc.
   * This may be called many times for the same SubMonitor instance. When this method
   * is called, the remaining space on the progress monitor is redistributed into the given
   * number of ticks.</p>
   *
   * <p>It doesn't matter how much progress has already been reported with this SubMonitor
   * instance. If you call setWorkRemaining(100), you will be able to report 100 more ticks of
   * work before the progress meter reaches 100%.</p>
   *
   * @param workRemaining total number of remaining ticks
   * @return the receiver
   */
  public final SubMonitor setWorkRemaining(int workRemaining)
  {
    checkCancelation();

    // Ensure we don't try to allocate negative ticks
    workRemaining = Math.max(0, workRemaining);

    // Ensure we don't cause division by zero
    if (totalForChildren > 0 && totalParent > usedForParent)
    {
      // Note: We want the following value to remain invariant after this method returns
      double remainForParent = totalParent * (1.0d - usedForChildren / totalForChildren);
      usedForChildren = workRemaining * (1.0d - remainForParent / (totalParent - usedForParent));
    }
    else
    {
      usedForChildren = 0.0d;
    }

    totalParent = totalParent - usedForParent;
    usedForParent = 0;
    totalForChildren = workRemaining;
    return this;
  }

  /**
   * Consumes the given number of child ticks, given as a double. Must only
   * be called if the monitor is in floating-point mode.
   *
   * @param ticks the number of ticks to consume
   * @return ticks the number of ticks to be consumed from parent
   */
  private int consume(double ticks)
  {
    if (totalParent == 0 || totalForChildren == 0)
    {
      return 0;
    }

    usedForChildren += ticks;

    if (usedForChildren > totalForChildren)
    {
      usedForChildren = totalForChildren;
    }
    else if (usedForChildren < 0.0)
    {
      usedForChildren = 0.0;
    }

    int parentPosition = (int)(totalParent * usedForChildren / totalForChildren);
    int delta = parentPosition - usedForParent;

    usedForParent = parentPosition;
    return delta;
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
   */
  public final boolean isCanceled()
  {
    return root.isCanceled();
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
   */
  public final void setTaskName(String name)
  {
    checkCancelation();

    if ((flags & SUPPRESS_SETTASKNAME) == 0)
    {
      root.setTaskName(name);
    }
  }

  /**
   * Starts a new main task. The string argument is ignored
   * if and only if the SUPPRESS_BEGINTASK flag has been set on this SubMonitor
   * instance.
   *
   * <p>This method is equivalent calling setWorkRemaining(...) on the receiver. Unless
   * the SUPPRESS_BEGINTASK flag is set, this will also be equivalent to calling
   * setTaskName(...) on the parent.</p>
   *
   * @param name new main task name
   * @param totalWork number of ticks to allocate
   *
   * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String, int)
   */
  public final void beginTask(String name, int totalWork)
  {
    if ((flags & SUPPRESS_BEGINTASK) == 0 && name != null)
    {
      root.setTaskName(name);
    }
    setWorkRemaining(totalWork);
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#done()
   */
  // Can't be final because ProbingSubMonitor overrides it.
  public void done()
  {
    cleanupActiveChild();
    int delta = totalParent - usedForParent;
    if (delta > 0)
    {
      root.worked(delta);
    }

    totalParent = 0;
    usedForParent = 0;
    totalForChildren = 0;
    usedForChildren = 0.0d;
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
   */
  public final void internalWorked(double work)
  {
    checkCancelation();
    cleanupActiveChild();

    int delta = consume(work > 0.0d ? work : 0.0d);
    if (delta != 0)
    {
      root.worked(delta);
    }
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
   */
  public final void subTask(String name)
  {
    checkCancelation();

    if ((flags & SUPPRESS_SUBTASK) == 0)
    {
      root.subTask(name);
    }
  }

  /**
   * Same as {@link #worked(int) worked(1)}.
   */
  public final void worked()
  {
    worked(DEFAULT_WORK);
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
   */
  // Can't be final because ProbingSubMonitor overrides it.
  public void worked(int work)
  {
    internalWorked(work);
  }

  /**
   * Same as {@link #setWorkRemaining(int) setWorkRemaining(totalParent - usedForParent)}.
   */
  public final void skipped(int ticks)
  {
    checkCancelation();
    setWorkRemaining(totalParent - usedForParent);
  }

  /**
   * Same as {@link #skipped(int) skipped(1)}.
   */
  public final void skipped()
  {
    skipped(DEFAULT_WORK);
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
   */
  public final void setCanceled(boolean b)
  {
    root.setCanceled(b);
  }

  /**
   * Same as {@link #newChild(int) newChild(1)}.
   */
  public final SubMonitor newChild()
  {
    return newChild(DEFAULT_WORK, SUPPRESS_BEGINTASK);
  }

  /**
   * <p>Creates a sub progress monitor that will consume the given number of ticks from the
   * receiver. It is not necessary to call <code>beginTask</code> or <code>done</code> on the
   * result. However, the resulting progress monitor will not report any work after the first
   * call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
   * or setWorkRemaining.</p>
   *
   * <p>Each SubMonitor only has one active child at a time. Each time newChild() is called, the
   * result becomes the new active child and any unused progress from the previously-active child is
   * consumed.</p>
   *
   * <p>This is property makes it unnecessary to call done() on a SubMonitor instance, since child
   * monitors are automatically cleaned up the next time the parent is touched.</p>
   *
   * <code><pre>
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 1: Typical usage of newChild
   *      void myMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *          doSomething(progress.newChild(50));
   *          doSomethingElse(progress.newChild(50));
   *      }
   *
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 2: Demonstrates the function of active children. Creating children
   *      // is sufficient to smoothly report progress, even if worked(...) and done()
   *      // are never called.
   *      void myMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          for (int i = 0; i < 100; i++) {
   *              // Creating the next child monitor will clean up the previous one,
   *              // causing progress to be reported smoothly even if we don't do anything
   *              // with the monitors we create
   *            progress.newChild(1);
   *          }
   *      }
   *
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 3: Demonstrates a common anti-pattern
   *      void wrongMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          // WRONG WAY: Won't have the intended effect, as only one of these progress
   *          // monitors may be active at a time and the other will report no progress.
   *          callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
   *      }
   *
   *      void rightMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
   *          Object someValue = computeValue(progress.newChild(50));
   *          callMethod(progress.newChild(50), someValue);
   *      }
   * </pre></code>
   *
   * @param totalWork number of ticks to consume from the receiver
   * @return new sub progress monitor that may be used in place of a new SubMonitor
   */
  public final SubMonitor newChild(int totalWork)
  {
    return newChild(totalWork, SUPPRESS_BEGINTASK);
  }

  /**
   * <p>Creates a sub progress monitor that will consume the given number of ticks from the
   * receiver. It is not necessary to call <code>beginTask</code> or <code>done</code> on the
   * result. However, the resulting progress monitor will not report any work after the first
   * call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
   * or setWorkRemaining.</p>
   *
   * <p>Each SubMonitor only has one active child at a time. Each time newChild() is called, the
   * result becomes the new active child and any unused progress from the previously-active child is
   * consumed.</p>
   *
   * <p>This is property makes it unnecessary to call done() on a SubMonitor instance, since child
   * monitors are automatically cleaned up the next time the parent is touched.</p>
   *
   * <code><pre>
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 1: Typical usage of newChild
   *      void myMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *          doSomething(progress.newChild(50));
   *          doSomethingElse(progress.newChild(50));
   *      }
   *
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 2: Demonstrates the function of active children. Creating children
   *      // is sufficient to smoothly report progress, even if worked(...) and done()
   *      // are never called.
   *      void myMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          for (int i = 0; i < 100; i++) {
   *              // Creating the next child monitor will clean up the previous one,
   *              // causing progress to be reported smoothly even if we don't do anything
   *              // with the monitors we create
   *            progress.newChild(1);
   *          }
   *      }
   *
   *      ////////////////////////////////////////////////////////////////////////////
   *      // Example 3: Demonstrates a common anti-pattern
   *      void wrongMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          // WRONG WAY: Won't have the intended effect, as only one of these progress
   *          // monitors may be active at a time and the other will report no progress.
   *          callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
   *      }
   *
   *      void rightMethod(IProgressMonitor parent) {
   *          SubMonitor progress = SubMonitor.convert(parent, 100);
   *
   *          // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
   *          Object someValue = computeValue(progress.newChild(50));
   *          callMethod(progress.newChild(50), someValue);
   *      }
   * </pre></code>
   *
   * @param totalWork number of ticks to consume from the receiver
   * @return new sub progress monitor that may be used in place of a new SubMonitor
   */
  public final SubMonitor newChild(int totalWork, int suppressFlags)
  {
    checkCancelation();

    double totalWorkDouble = totalWork > 0 ? totalWork : 0.0d;
    totalWorkDouble = Math.min(totalWorkDouble, totalForChildren - usedForChildren);
    cleanupActiveChild();

    // Compute the flags for the child. We want the net effect to be as though the child is
    // delegating to its parent, even though it is actually talking directly to the root.
    // This means that we need to compute the flags such that - even if a label isn't
    // suppressed by the child - if that same label would have been suppressed when the
    // child delegated to its parent, the child must explicitly suppress the label.
    int childFlags = SUPPRESS_NONE;

    if ((flags & SUPPRESS_SETTASKNAME) != 0)
    {
      // If the parent was ignoring labels passed to setTaskName, then the child will ignore
      // labels passed to either beginTask or setTaskName - since both delegate to setTaskName
      // on the parent
      childFlags |= SUPPRESS_SETTASKNAME | SUPPRESS_BEGINTASK;
    }

    if ((flags & SUPPRESS_SUBTASK) != 0)
    {
      // If the parent was suppressing labels passed to subTask, so will the child.
      childFlags |= SUPPRESS_SUBTASK;
    }

    // Note: the SUPPRESS_BEGINTASK flag does not affect the child since there
    // is no method on the child that would delegate to beginTask on the parent.
    childFlags |= suppressFlags;

    SubMonitor result = createSubMonitor(root, consume(totalWorkDouble), (int)totalWorkDouble, childFlags);
    lastSubMonitor = result;
    return result;
  }

  public void childDone()
  {
    // Do nothing
  }

  private void cleanupActiveChild()
  {
    if (lastSubMonitor == null)
    {
      return;
    }

    IProgressMonitor child = lastSubMonitor;
    lastSubMonitor = null;
    child.done();
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
   */
  public final void clearBlocked()
  {
    checkCancelation();
    root.clearBlocked();
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
   */
  public final void setBlocked(IStatus reason)
  {
    checkCancelation();
    root.setBlocked(reason);
  }

  protected static boolean eq(Object o1, Object o2)
  {
    if (o1 == null)
    {
      return o2 == null;
    }
    if (o2 == null)
    {
      return false;
    }
    return o1.equals(o2);
  }

  /**
   * Enumerates the possible probing mode values {@link #OFF}, {@link #STANDARD} and {@link #FULL}.
   *
   * @author Eike Stepper
   * @since 3.4
   */
  public enum ProbingMode
  {
    OFF, STANDARD, FULL;

    public static final ProbingMode DEFAULT = getDefault();

    private static ProbingMode getDefault()
    {
      String mode = System.getProperty("submonitor.probing");
      if (FULL.toString().equalsIgnoreCase(mode))
      {
        return FULL;
      }

      if (STANDARD.toString().equalsIgnoreCase(mode) || Boolean.TRUE.toString().equalsIgnoreCase(mode))
      {
        return STANDARD;
      }

      return OFF;
    }
  }
}
