package org.checkerframework.checker.nullness.util;

import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.AnnotatedFor;

/**
 * Utility class for the Nullness Checker.
 *
 * <p>To avoid the need to write the NullnessUtil class name, do:
 *
 * <pre>import static org.checkerframework.checker.nullness.util.NullnessUtil.castNonNull;</pre>
 *
 * or
 *
 * <pre>import static org.checkerframework.checker.nullness.util.NullnessUtil.*;</pre>
 *
 * <p><b>Runtime Dependency</b>: If you use this class, you must distribute (or link to) {@code
 * checker-qual.jar}, along with your binaries. Or, you can can copy this class into your own
 * project.
 */
@SuppressWarnings({
  "nullness", // Nullness utilities are trusted regarding nullness.
  "cast" // Casts look redundant if Nullness Checker is not run.
})
@AnnotatedFor("nullness")
public final class NullnessUtil {

  private NullnessUtil() {
    throw new AssertionError("shouldn't be instantiated");
  }

  /**
   * A method that suppresses warnings from the Nullness Checker.
   *
   * <p>The method takes a possibly-null reference, unsafely casts it to have the @NonNull type
   * qualifier, and returns it. The Nullness Checker considers both the return value, and also the
   * argument, to be non-null after the method call. Therefore, the {@code castNonNull} method can
   * be used either as a cast expression or as a statement. The Nullness Checker issues no warnings
   * in any of the following code:
   *
   * <pre><code>
   *   // one way to use as a cast:
   *  {@literal @}NonNull String s = castNonNull(possiblyNull1);
   *
   *   // another way to use as a cast:
   *   castNonNull(possiblyNull2).toString();
   *
   *   // one way to use as a statement:
   *   castNonNull(possiblyNull3);
   *   possiblyNull3.toString();`
   * </code></pre>
   *
   * The {@code castNonNull} method is intended to be used in situations where the programmer
   * definitively knows that a given reference is not null, but the type system is unable to make
   * this deduction. It is not intended for defensive programming, in which a programmer cannot
   * prove that the value is not null but wishes to have an earlier indication if it is. See the
   * Checker Framework Manual for further discussion.
   *
   * <p>The method throws {@link AssertionError} if Java assertions are enabled and the argument is
   * {@code null}. If the exception is ever thrown, then that indicates that the programmer misused
   * the method by using it in a circumstance where its argument can be null.
   *
   * @param <T> the type of the reference
   * @param ref a reference of @Nullable type, that is non-null at run time
   * @return the argument, casted to have the type qualifier @NonNull
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T castNonNull(@Nullable T ref) {
    assert ref != null : "Misuse of castNonNull: called with a null argument";
    return (@NonNull T) ref;
  }

  /**
   * Suppress warnings from the Nullness Checker, with a custom error message. See {@link
   * #castNonNull(Object)} for documentation.
   *
   * @see #castNonNull(Object)
   * @param <T> the type of the reference
   * @param ref a reference of @Nullable type, that is non-null at run time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull
   */
  public static @EnsuresNonNull("#1") <T extends @Nullable Object> @NonNull T castNonNull(
      @Nullable T ref, String message) {
    assert ref != null : "Misuse of castNonNull: called with a null argument: " + message;
    return (@NonNull T) ref;
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [] castNonNullDeep(
      T @Nullable [] arr) {
    return (@NonNull T[]) castNonNullArray(arr, null);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [] castNonNullDeep(
      T @Nullable [] arr, String message) {
    return (@NonNull T[]) castNonNullArray(arr, message);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type of the component type of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][] castNonNullDeep(
      T @Nullable [] @Nullable [] arr) {
    return (@NonNull T[][]) castNonNullArray(arr, null);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type of the component type of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][] castNonNullDeep(
      T @Nullable [] @Nullable [] arr, String message) {
    return (@NonNull T[][]) castNonNullArray(arr, message);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type (three levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] arr) {
    return (@NonNull T[][][]) castNonNullArray(arr, null);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type (three levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] arr, String message) {
    return (@NonNull T[][][]) castNonNullArray(arr, message);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr) {
    return (@NonNull T[][][][]) castNonNullArray(arr, null);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type (four levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr, String message) {
    return (@NonNull T[][][][]) castNonNullArray(arr, message);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type (four levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr) {
    return (@NonNull T[][][][][]) castNonNullArray(arr, null);
  }

  /**
   * Like castNonNull, but whereas that method only checks and casts the reference itself, this
   * traverses all levels of the argument array. The array is recursively checked to ensure that all
   * elements at every array level are non-null.
   *
   * @param <T> the component type (five levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if this method is misused
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   * @see #castNonNull(Object)
   */
  @EnsuresNonNull("#1")
  public static <T extends @Nullable Object> @NonNull T @NonNull [][][][][] castNonNullDeep(
      T @Nullable [] @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr, String message) {
    return (@NonNull T[][][][][]) castNonNullArray(arr, message);
  }

  /**
   * The implementation of castNonNullDeep.
   *
   * @param <T> the component type (five levels in) of the array
   * @param arr an array all of whose elements, and their elements recursively, are non-null at run
   *     time
   * @param message text to include if there is a non-null value, or null to use uncustomized
   *     message
   * @return the argument, casted to have the type qualifier @NonNull at all levels
   */
  private static <T extends @Nullable Object> @NonNull T @NonNull [] castNonNullArray(
      T @Nullable [] arr, @Nullable String message) {
    assert arr != null
        : "Misuse of castNonNullArray: called with a null array argument"
            + ((message == null) ? "" : (": " + message));
    for (int i = 0; i < arr.length; ++i) {
      assert arr[i] != null
          : "Misuse of castNonNull: called with a null array element"
              + ((message == null) ? "" : (": " + message));
      checkIfArray(arr[i], message);
    }
    return (@NonNull T[]) arr;
  }

  /**
   * If the argument is an array, requires it to be non-null at all levels.
   *
   * @param ref a value; if an array, all of its elements, and their elements recursively, are
   *     non-null at run time
   * @param message text to include if there is a non-null value, or null to use uncustomized
   *     message
   */
  private static void checkIfArray(@NonNull Object ref, @Nullable String message) {
    assert ref != null
        : "Misuse of checkIfArray: called with a null argument"
            + ((message == null) ? "" : (": " + message));
    Class<?> comp = ref.getClass().getComponentType();
    if (comp != null) {
      // comp is non-null for arrays, otherwise null.
      if (comp.isPrimitive()) {
        // Nothing to do for arrays of primitive type: primitives are
        // never null.
      } else {
        castNonNullArray((Object[]) ref, message);
      }
    }
  }
}
