package replicant.spy.tools;

import arez.Arez;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.testng.annotations.Test;
import replicant.AbstractReplicantTest;
import replicant.AreaOfInterest;
import replicant.ChannelAddress;
import replicant.Replicant;
import replicant.spy.AreaOfInterestCreatedEvent;
import static org.testng.Assert.*;

public class SpyEventProcessorTest
  extends AbstractReplicantTest
{
  private static class TestSpyEventProcessor
    extends AbstractSpyEventProcessor
  {
    int _handleUnhandledEventCallCount;

    @Override
    protected void handleUnhandledEvent( @Nonnull final Object event )
    {
      super.handleUnhandledEvent( event );
      _handleUnhandledEventCallCount += 1;
    }
  }

  @Test
  public void handleUnhandledEvent()
    throws Throwable
  {
    final TestSpyEventProcessor processor = new TestSpyEventProcessor();

    final Object event = new Object();
    processor.onSpyEvent( event );

    assertEquals( processor._handleUnhandledEventCallCount, 1 );
  }

  @Test
  public void handleEvent()
    throws Throwable
  {
    final TestSpyEventProcessor processor = new TestSpyEventProcessor();

    final AtomicInteger callCount = new AtomicInteger();
    processor.on( AreaOfInterestCreatedEvent.class, e -> callCount.incrementAndGet() );

    final AreaOfInterest areaOfInterest =
      Arez.context().safeAction( () -> Replicant.context().createOrUpdateAreaOfInterest( new ChannelAddress( G.G1 ),
                                                                                         null ) );

    final AreaOfInterestCreatedEvent event = new AreaOfInterestCreatedEvent( areaOfInterest );

    assertEquals( callCount.get(), 0 );
    processor.onSpyEvent( event );
    assertEquals( callCount.get(), 1 );
  }

  @Test
  public void onFailsOnDuplicates()
    throws Throwable
  {
    final TestSpyEventProcessor processor = new TestSpyEventProcessor();

    final Consumer<AreaOfInterestCreatedEvent> handler = e -> {
    };
    processor.on( AreaOfInterestCreatedEvent.class, handler );
    final IllegalStateException exception =
      expectThrows( IllegalStateException.class, () -> processor.on( AreaOfInterestCreatedEvent.class, handler ) );
    assertEquals( exception.getMessage(),
                  "Replicant-0157: Attempting to call AbstractSpyEventProcessor.on() to register a processor for type class replicant.spy.AreaOfInterestCreatedEvent but an existing processor already exists for type" );
  }

  enum G
  {
    G1
  }
}

@@ -27,26 +27,8 @@
 s;%0A%0A
-import arez.Arez;%0A
 impo
@@ -222,151 +222,8 @@
 st;%0A
-import replicant.AreaOfInterest;%0Aimport replicant.ChannelAddress;%0Aimport replicant.Replicant;%0Aimport replicant.spy.AreaOfInterestCreatedEvent;%0A
 impo
@@ -635,24 +635,66 @@
 %0A    %7D%0A  %7D%0A%0A
+  private static class FakeEvent%0A  %7B%0A  %7D%0A%0A
   @Test%0A  pu
@@ -1180,37 +1180,20 @@
 sor.on( 
-AreaOfInterestCreated
+Fake
 Event.cl
@@ -1248,349 +1248,40 @@
 nal 
-AreaOfInterest areaOfInterest =%0A      Arez.context().safeAction( () -%3E Replicant.context().createOrUpdateAreaOfInterest( new ChannelAddress( G.G1 ),%0A                                                                                         null ) );%0A%0A    final AreaOfInterestCreatedEvent event = new AreaOfInterestCreatedEvent( areaOfInterest 
+FakeEvent event = new FakeEvent(
 );%0A%0A
@@ -1562,37 +1562,20 @@
 onsumer%3C
-AreaOfInterestCreated
+Fake
 Event%3E h
@@ -1615,37 +1615,20 @@
 sor.on( 
-AreaOfInterestCreated
+Fake
 Event.cl
@@ -1756,37 +1756,20 @@
 sor.on( 
-AreaOfInterestCreated
+Fake
 Event.cl
@@ -1970,29 +1970,40 @@
 spy.
-AreaOfInterestCreated
+tools.SpyEventProcessorTest$Fake
 Even

Use FakeEvent to decouple from other replicant infrastructure