package org.realityforge.imit.client;

import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class EntityRepositoryTest
{
  @Test
  public void registerAndDeregisterHasExpectedEffects()
  {
    final EntityRepository r = new EntityRepositoryImpl();
    final Class<B> parentType = B.class;
    final Class<A> type = A.class;
    final String id = "A";
    final A entity = new A();

    // If I register an ID it should be accessible in all weird and wonderful ways
    r.registerEntity( type, id, entity );

    assertPresent( r, type, id, entity );
    assertPresent( r, parentType, id, entity );
    assertNotPresent( r, type, "X" );
    assertNotPresent( r, parentType, "X" );

    r.deregisterEntity( type, id );

    assertNotPresent( r, type, id );
    assertNotPresent( r, parentType, id );
    assertNotPresentInSet( r, type, entity );
  }

  @Test
  public void duplicateRegisterRaisesException()
  {
    final EntityRepository r = new EntityRepositoryImpl();
    final Class<A> type = A.class;
    final String id = "A";
    final A entity = new A();

    r.registerEntity( type, id, entity );

    try
    {
      r.registerEntity( type, id, entity );
    }
    catch ( Exception e )
    {
      return;
    }
    fail( "Expected to raise an exception when re-registering an entity" );
  }

  @Test
  public void deregisterNonExistentRaisesException()
  {
    final EntityRepository r = new EntityRepositoryImpl();
    final Class<A> type = A.class;
    final String id = "A";

    try
    {
      r.deregisterEntity( type, id );
    }
    catch ( Exception e )
    {
      return;
    }
    fail( "Expected to raise an exception when de-registering an entity not present" );
  }

  private void assertPresent( final EntityRepository r, final Class<?> type, final Object id, final Object entity )
  {
    assertCanFind( r, type, id, entity );
    assertCanGet( r, type, id, entity );
    assertTrue( r.findAll( type ).contains( entity ) );
  }

  private void assertNotPresent( final EntityRepository r, final Class<?> type, final Object id )
  {
    assertCanNotFind( r, type, id );
    assertCanNotGet( r, type, id );
  }

  private void assertNotPresentInSet( final EntityRepository r, final Class<?> type, final Object entity )
  {
    assertFalse( r.findAll( type ).contains( entity ) );
  }

  private void assertCanFind( final EntityRepository r, final Class<?> type, final Object id, final Object entity )
  {
    assertEquals( entity, r.findByID( type, id ) );
  }

  private void assertCanGet( final EntityRepository r, final Class<?> type, final Object id, final Object entity )
  {
    assertEquals( entity, r.getByID( type, id ) );
  }

  private void assertCanNotFind( final EntityRepository r, final Class<?> type, final Object id )
  {
    assertNull( r.findByID( type, id ) );
  }

  private void assertCanNotGet( final EntityRepository r, final Class<?> type, final Object id )
  {
    boolean failed;
    try
    {
      r.getByID( type, id );
      failed = false;
    }
    catch ( final Exception e )
    {
      failed = true;
    }
    if ( !failed )
    {
      fail( "Expected getByID to fail with exception for bad ID" );
    }
  }


  static class B
  {
  }

  static class A
    extends B
  {
  }
}

@@ -1189,35 +1189,52 @@
 %0A    %7D%0A    catch
- 
 ( 
+final IllegalState
 Exception e )%0A  
@@ -1229,32 +1229,190 @@
 ption e )%0A    %7B%0A
+      assertEquals( %22Attempting to register duplicate entity with type '%22 + type.getName() + %22' and id = '%22 + id + %22'%22,%0A                    e.getMessage() );%0A
       return;%0A  
@@ -1750,19 +1750,36 @@
    catch
- 
 ( 
+final IllegalState
 Exceptio
@@ -1786,24 +1786,188 @@
 n e )%0A    %7B%0A
+      assertEquals( %22Attempting to de-register non existent entity with type '%22 + type.getName() +%0A                    %22' and id = '%22 + id + %22'%22, e.getMessage() );%0A
       return
@@ -3390,17 +3390,16 @@
 atch
- 
 ( final 
 Exce
@@ -3394,16 +3394,28 @@
 ( final 
+IllegalState
 Exceptio
@@ -3418,32 +3418,174 @@
 ption e )%0A    %7B%0A
+      assertEquals( %22Unable to locate entity with type '%22 + type.getName() + %22' and id = '%22 + id + %22'%22,%0A                    e.getMessage() );%0A
       failed = t
@@ -3601,17 +3601,16 @@
 %7D%0A    if
- 
 ( !faile
@@ -3742,16 +3742,18 @@
 class A%0A
+  
     exte

Make the tests enforce the exception message o failures