package org.realityforge.arez.extras;

import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.realityforge.arez.ArezContext;
import org.realityforge.arez.ComputedValue;
import org.realityforge.arez.Observer;
import org.realityforge.arez.Procedure;
import org.realityforge.arez.SafeFunction;

/**
 * This class is used to wait until a condition is true, then run effect and remove watch.
 *
 * <p>This is a good example of how the primitives provided by Arez can be glued together
 * to create higher level reactive elements.</p>
 */
public final class Watcher
{
  @Nonnull
  private final ComputedValue<Boolean> _conditionValue;
  private final Observer _observer;

  public Watcher( @Nonnull final ArezContext context,
                  @Nullable final String name,
                  final boolean mutation,
                  @Nonnull final SafeFunction<Boolean> condition,
                  @Nonnull final Procedure effect )
  {
    _conditionValue = context.createComputedValue( name, condition, Objects::equals );
    final Procedure procedure = () -> {
      if ( Boolean.TRUE == _conditionValue.get() )
      {
        context.procedure( name, mutation, effect );
        dispose();
      }
    };
    _observer = context.autorun( name, mutation, procedure, true );
  }

  public void dispose()
  {
    _conditionValue.dispose();
    _observer.dispose();
  }
}

@@ -432,16 +432,269 @@
 tch.%0A *%0A
+ * %3Cp%3EThe condition function is run in a read-only, tracking transaction and will be re-evaluated%0A * any time any of the observed elements are updated. The effect procedure is run in either a%0A * read-only or read-write, non-tracking transaction.%3C/p%3E%0A *%0A
  * %3Cp%3ETh
@@ -857,16 +857,76 @@
 tcher%0A%7B%0A
+  /**%0A   * The Computed value representing condition.%0A   */%0A
   @Nonnu
@@ -990,42 +990,542 @@
 ;%0A  
-private final Observer _observer;%0A
+/**%0A   * The observer that is observing condition, waiting until it is true.%0A   */%0A  private final Observer _observer;%0A%0A  /**%0A   * Create the watcher.%0A   *%0A   * @param context   the Arez system to watch.%0A   * @param name      the debug name (if any) used when naming the underlying Arez resources.%0A   * @param mutation  true if the effect can mutate state, false otherwise.%0A   * @param condition The function that determines when th effect is run.%0A   * @param effect    The procedure that is executed when the condition is true.%0A   */
 %0A  p
@@ -2132,16 +2132,117 @@
 );%0A  %7D%0A%0A
+  /**%0A   * Cancel the watch if it has not been triggered and release all underlying resources.%0A   */%0A
   public

Add some javadocs