package org.realityforge.arez;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import org.realityforge.guiceyloops.shared.ValueUtil;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class ComputedValueTest
  extends AbstractArezTest
{
  @Test
  public void initialState()
    throws Exception
  {
    final ArezContext context = new ArezContext();
    final String name = ValueUtil.randomString();
    final SafeFunction<String> function = () -> "";
    final EqualityComparator<String> comparator = Objects::equals;
    final ComputedValue<String> computedValue = new ComputedValue<>( context, name, function, comparator );

    assertEquals( computedValue.getName(), name );
    assertEquals( computedValue.getContext(), context );
    assertEquals( computedValue.toString(), name );

    // Value starts out as null
    assertEquals( computedValue.getValue(), null );

    // Verify the linking of all child elements
    assertEquals( computedValue.getObserver().getName(), name );
    assertEquals( computedValue.getObserver().isDerivation(), true );
    assertEquals( computedValue.getObserver().getComputedValue(), computedValue );
    assertEquals( computedValue.getObservable().getName(), name );
    assertEquals( computedValue.getObservable().isCalculated(), true );
    assertEquals( computedValue.getObservable().getOwner(), computedValue.getObserver() );
  }

  @Test
  public void computeValue()
    throws Exception
  {
    final ArezContext context = new ArezContext();
    final String name = ValueUtil.randomString();
    final AtomicReference<String> value = new AtomicReference<>();
    value.set( "" );
    final SafeFunction<String> function = value::get;
    final EqualityComparator<String> comparator = Objects::equals;
    final ComputedValue<String> computedValue = new ComputedValue<>( context, name, function, comparator );

    assertEquals( computedValue.computeValue(), "" );

    value.set( "XXX" );

    assertEquals( computedValue.computeValue(), "XXX" );
  }
}

@@ -2048,11 +2048,1211 @@
 %22 );%0A  %7D
+%0A%0A  @Test%0A  public void compute()%0A    throws Exception%0A  %7B%0A    final ArezContext context = new ArezContext();%0A    final String name = ValueUtil.randomString();%0A    final AtomicReference%3CString%3E value = new AtomicReference%3C%3E();%0A    final String value1 = ValueUtil.randomString();%0A    final String value2 = ValueUtil.randomString();%0A    final SafeFunction%3CString%3E function = value::get;%0A    final EqualityComparator%3CString%3E comparator = Objects::equals;%0A    final ComputedValue%3CString%3E computedValue = new ComputedValue%3C%3E( context, name, function, comparator );%0A%0A    setCurrentTransaction( context, computedValue.getObserver() );%0A%0A    final Observer observer = newReadOnlyObserver( context );%0A    observer.setState( ObserverState.POSSIBLY_STALE );%0A    computedValue.getObserver().getDerivedValue().addObserver( observer );%0A    observer.getDependencies().add( computedValue.getObservable() );%0A%0A    computedValue.getObservable().setLeastStaleObserverState( ObserverState.POSSIBLY_STALE );%0A%0A    computedValue.setValue( value1 );%0A%0A    value.set( value2 );%0A%0A    computedValue.compute();%0A%0A    assertEquals( computedValue.getValue(), value2 );%0A    assertEquals( observer.getState(), ObserverState.STALE );%0A  %7D
 %0A%7D%0A

Test compute where value changes