package arez.annotations;

import arez.ComputableValue;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;

/**
 * Methods marked with this annotation are <a href="https://en.wikipedia.org/wiki/Memoization">memoized</a> while
 * activated which typically means they have an observer. These methods are typically backed with one or more
 * {@link ComputableValue} instances.
 *
 * <p>The return value should be derived from the method parameters and any other {@link Observable} properties
 * or {@link Computed} properties accessed within the scope of the method. The he value returned by the method
 * should not change unless the state of the {@link Observable} properties or {@link Computed} properties change.
 * If the return value can change outside of the above scenarios it is important to set the {@link #depType()}
 * to {@link DepType#AREZ_OR_EXTERNAL} and explicitly report possible changes to the derived value by invoking
 * the {@link ComputableValue#reportPossiblyChanged()} on the {@link ComputableValue} returned from a method
 * annotated by the {@link ComputableValueRef} that is linked to the method marked with this annotation.</p>
 *
 * <p>The method is wrapped in a READ_ONLY transaction and thus can not modify other state in the system.</p>
 *
 * <p>The enhanced method is implemented by creating a separate {@link ComputableValue} instance for each unique
 * combination of parameters that are passed to the method. When the {@link ComputableValue} is deactivated, a hook
 * triggers that removes the {@link ComputableValue} from the local cache. If the method has zero parameter then
 * the method is backed by a single {@link ComputableValue} instance.</p>
 *
 * <p>The method that is annotated with this annotation must comply with the additional constraints:</p>
 * <ul>
 * <li>Must not be annotated with any other arez annotation</li>
 * <li>Must return a value</li>
 * <li>Must not be private</li>
 * <li>Must not be static</li>
 * <li>Must not be final</li>
 * <li>Must not be abstract</li>
 * <li>Must not throw exceptions</li>
 * </ul>
 */
@Documented
@Target( ElementType.METHOD )
public @interface Computed
{
  /**
   * Return the name of the ComputableValue relative to the component.
   * The value must conform to the requirements of a java identifier.
   * The name must also be unique across {@link Observable}s,
   * {@link Computed}s and {@link Action}s within the scope of the
   * {@link ArezComponent} annotated element.
   *
   * @return the name of the ComputableValue relative to the component.
   */
  @Nonnull
  String name() default "<default>";

  /**
   * A flag indicating whether the computable should be "kept alive". A computable that is kept alive
   * is activated on creation and never deactivates. This is useful if the computable property is only
   * accessed from within actions but should be kept up to date and not recomputed on each access.
   *
   * @return true to keep computable alive.
   */
  boolean keepAlive() default false;

  /**
   * The priority of the underlying ComputableValue observer
   *
   * @return the priority of the ComputableValue observer.
   */
  Priority priority() default Priority.NORMAL;

  /**
   * Flag controlling whether the underlying observer can observe ComputableValue instances with lower priorities.
   * The default value of false will result in an invariant failure (in development mode) if a lower priority
   * dependency is observed by the observer. This is to prevent priority inversion when scheduling a higher
   * priority observer is dependent upon a lower priority computable value. If the value is true then the no
   * invariant failure is triggered and the component relies on the component author to handle possible priority
   * inversion.
   *
   * @return false if observing lower priority dependencies should result in invariant failure in development mode.
   */
  boolean observeLowerPriorityDependencies() default false;

  /**
   * Enum indicating whether the value of the computable is derived from arez elements and/or external dependencies.
   * If set to {@link DepType#AREZ} then Arez will verify that the method annotated by this annotation accesses arez
   * elements (i.e. instances of {@link arez.ObservableValue} or instances of {@link ComputableValue}). If set to
   * {@link DepType#AREZ_OR_NONE} then the runtime will allow computable to exist with no dependencies. If set
   * to {@link DepType#AREZ_OR_EXTERNAL} then the component must define a {@link ComputableValueRef} method and should invoke
   * {@link ComputableValue#reportPossiblyChanged()} when the non-arez dependencies are changed.
   *
   * @return the types of dependencies allowed on the computable.
   */
  @Nonnull
  DepType depType() default DepType.AREZ;

  /**
   * True if invocations of the computable must be executed in an {@link arez.Environment}.
   *
   * @return true if invocations of the computable must be executed in an {@link arez.Environment}, false otherwise.
   */
  boolean requireEnvironment() default false;

  /**
   * Return true if the return value of the comptable value should be reported to the Arez spy subsystem.
   * It is useful to disable reporting for large, circular or just uninteresting parameters to the spy infrastructure.
   *
   * @return true to report the return value, false otherwise.
   */
  boolean reportResult() default true;
}

@@ -2253,32 +2253,37 @@
    * Return the 
+root 
 name of the Comp
@@ -2274,35 +2274,33 @@
 name of the 
-ComputableV
+element v
 alue relativ
@@ -2319,24 +2319,179 @@
 ponent.%0A   *
+ If the method has parameters then the name will be used in combination with a sequence%0A   * when naming the synthesized %7B@link ComputableValue%7D instances.
  The value m
@@ -2504,16 +2504,21 @@
 nform to
+%0A   *
  the req
@@ -2548,21 +2548,16 @@
 ntifier.
-%0A   *
  The nam
@@ -2737,24 +2737,29 @@
 @return the 
+root 
 name of the 
@@ -2758,31 +2758,23 @@
  of the 
-ComputableValue
+element
  relativ

Update javadocs on naming