package org.realityforge.arez.api2;

import java.util.function.Supplier;
import javax.annotation.Nonnull;
import org.jetbrains.annotations.Contract;

/**
 * A utility class used to perform assertions and invariant checks.
 */
final class Guards
{
  private Guards()
  {
  }

  /**
   * Check an invariant in code base.
   * If the condition is false then an {@link IllegalStateException} is thrown.
   * The invariant check will be skipped unless the configuration setting {@link ArezConfig#checkInvariants()}
   * is true. A null message is used rather than supplied message unless {@link ArezConfig#verboseErrorMessages()}
   * is true.
   *
   * @param condition the condition to check.
   * @param message   the message supplier used if verbose messages enabled.
   * @throws IllegalStateException if condition returns false.
   */
  static void invariant( @Nonnull final Supplier<Boolean> condition,
                         @Nonnull final Supplier<String> message )
  {
    if ( ArezConfig.checkInvariants() && !condition.get() )
    {
      fail( message );
    }
  }

  /**
   * Throw an IllegalStateException with supplied detail message.
   * The exception is not thrown unless {@link ArezConfig#checkInvariants()} is true.
   * The exception will ignore the supplied message unless {@link ArezConfig#verboseErrorMessages()} is true.
   *
   * @param message the message supplier used if verbose messages enabled.
   * @throws IllegalStateException when called.
   */
  @Contract( "_ -> fail" )
  static void fail( @Nonnull final Supplier<String> message )
  {
    if ( ArezConfig.checkInvariants() )
    {
      if ( ArezConfig.verboseErrorMessages() )
      {
        throw new IllegalStateException( ArezUtil.safeGetString( message ) );
      }
      else
      {
        throw new IllegalStateException();
      }
    }
  }
}

@@ -1011,36 +1011,435 @@
 s() 
-&& !condition.get() )%0A    %7B%0A
+)%0A    %7B%0A      boolean conditionResult = false;%0A      try%0A      %7B%0A        conditionResult = condition.get();%0A      %7D%0A      catch ( final Throwable t )%0A      %7B%0A        fail( () -%3E %22Error checking condition.%5Cn%22 +%0A                    %22Message: %22 + ArezUtil.safeGetString( message ) + %22%5Cn%22 +%0A                    %22Throwable:%5Cn%22 +%0A                    ArezUtil.throwableToString( t ) );%0A      %7D%0A      if ( !conditionResult )%0A      %7B%0A  
     
@@ -1453,24 +1453,32 @@
  message );%0A
+      %7D%0A
     %7D%0A  %7D%0A%0A 

Handle scenario where checking the condition produces an error