package org.realityforge.arez.examples;

import java.util.Timer;
import java.util.TimerTask;
import javax.annotation.Nonnull;
import org.jetbrains.annotations.TestOnly;
import org.realityforge.arez.ArezContext;
import org.realityforge.arez.Observable;
import org.realityforge.arez.Observer;

public final class TimerExample
{
  public static abstract class TimeModel
  {
    public abstract long getTime();

    public abstract void setTime( long time );
    public void updateTime()
    {
      setTime( System.currentTimeMillis() );
    }
  }

  public static class TimeModelImpl
    extends TimeModel
  {
    private final Observable $_time;
    private long _time;

    public TimeModelImpl( @Nonnull final ArezContext context )
    {
      $_time = context.createObservable( "TimeModel.time" );
    }

    @Override
    public long getTime()
    {
      $_time.reportObserved();
      return _time;
    }

    @Override
    public void setTime( final long time )
    {
      if ( _time != time )
      {
        $_time.reportChanged();
        _time = time;
      }
    }

    @TestOnly
    @Nonnull
    public Observable getTimeObservable()
    {
      return $_time;
    }
  }

  public static void main( final String[] args )
    throws Exception
  {
    final ArezContext context = new ArezContext();

    final TimeModelImpl timeModel = new TimeModelImpl( context );

    context.procedure( "Initial setup", true, null, timeModel::updateTime );

    final Observer timePrinter =
      context.createObserver( "TimePrinter",
                              false,
                              o -> System.out.println( "Current time: " + timeModel.getTime() ),
                              true );

    final Timer timer = new Timer();
    timer.schedule( new TimerTask()
    {
      @Override
      public void run()
      {
        try
        {
          context.procedure( "Subsequent update", true, null, timeModel::updateTime );
        }
        catch ( final Exception e )
        {
          e.printStackTrace();
        }
      }
    }, 0, 100 );

    timer.schedule( new TimerTask()
    {
      @Override
      public void run()
      {
        System.out.println( timeModel.getTimeObservable() );
        System.out.println( timePrinter + "::Active=" + timePrinter.isActive() );
      }
    }, 0, 1000 );
    Thread.sleep( 10 * 1000 );
    System.exit( 0 );
  }
}

@@ -86,16 +86,51 @@
 erTask;%0A
+import javax.annotation.Generated;%0A
 import j
@@ -274,20 +274,67 @@
 z.Observ
-able
+er;%0Aimport org.realityforge.arez.annotations.Action
 ;%0Aimport
@@ -356,24 +356,38 @@
 ge.arez.
+annotations.
 Observ
+abl
 e
-r
 ;%0A%0Apubli
@@ -456,24 +456,40 @@
 meModel%0A  %7B%0A
+    @Observable%0A
     public a
@@ -509,24 +509,40 @@
 getTime();%0A%0A
+    @Observable%0A
     public a
@@ -571,24 +571,37 @@
 long time );
+%0A%0A    @Action
 %0A    public 
@@ -672,32 +672,64 @@
 ) );%0A    %7D%0A  %7D%0A%0A
+  @Generated( %22ArezGenerator%22 )%0A
   public static 
@@ -788,24 +788,46 @@
 ivate final 
+org.realityforge.arez.
 Observable $
@@ -1304,16 +1304,38 @@
  public 
+org.realityforge.arez.
 Observab

Annotate classes as if the fields are observable