import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.framework.qual.DefaultQualifier;

/**
 * The component type of newly created arrays is always @Nullable, also for boxed types. This is an
 * expanded version of the test case for Issue 151:
 * https://github.com/typetools/checker-framework/issues/151
 */
public class ArrayCreationNullable {

  void testObjectArray(@NonNull Object @NonNull [] p) {
    @NonNull Object @NonNull [] objs;
    // :: error: (new.array)
    objs = new Object[10];
    objs[0].toString();
    // :: error: (assignment)
    objs = new @Nullable Object[10];
    objs[0].toString();
    // :: error: (new.array)
    objs = new @NonNull Object[10];
    objs[0].toString();
    // Allowed.
    objs = p;
    objs[0].toString();
  }

  @DefaultQualifier(NonNull.class)
  void testObjectArray2() {
    Object[] objs;
    // Even if the default qualifier is NonNull, array component
    // types must be Nullable.
    // :: error: (new.array)
    objs = new Object[10];
    objs[0].toString();
  }

  void testInitializers() {
    Object[] objs = {1, 2, 3};
    objs = new Integer[] {1, 2, 3};
    objs = new Object[] {new Object(), "ha"};

    @NonNull Object[] objs2 = {};
    // :: error: (assignment)
    objs2 = new Integer[] {1, null, 3};
    // :: error: (assignment)
    objs2 = new Object[] {new Object(), "ha", null};

    @NonNull Object[] objs3 = new Integer[] {1, 2, 3};
    objs3 = new Integer[] {1, 2, 3};
    // :: error: (assignment)
    objs3 = new Integer[] {1, 2, 3, null};

    (new Integer[] {1, 2, 3})[0].toString();
    // :: error: (dereference.of.nullable)
    (new Integer[] {1, 2, 3, null})[0].toString();

    // The assignment context is used to infer a @Nullable component type.
    @Nullable Object[] objs4 = new Integer[] {1, 2, 3};
    // :: error: (dereference.of.nullable)
    objs4[0].toString();
    objs4 = new Integer[] {1, 2, 3};
  }

  void testStringArray(@NonNull String @NonNull [] p) {
    @NonNull String @NonNull [] strs;
    // :: error: (new.array)
    strs = new String[10];
    strs[0].toString();
    // :: error: (assignment)
    strs = new @Nullable String[10];
    strs[0].toString();
    // :: error: (new.array)
    strs = new @NonNull String[10];
    strs[0].toString();
    // Allowed.
    strs = p;
    strs[0].toString();
  }

  void testIntegerArray(@NonNull Integer @NonNull [] p) {
    @NonNull Integer @NonNull [] ints;
    // :: error: (new.array)
    ints = new Integer[10];
    ints[0].toString();
    // :: error: (assignment)
    ints = new @Nullable Integer[10];
    ints[0].toString();
    // :: error: (new.array)
    ints = new @NonNull Integer[10];
    ints[0].toString();
    // Allowed.
    ints = p;
    ints[0].toString();
  }

  // The component type of zero-length arrays can be non-null - they will always generate
  // IndexOutOfBoundsExceptions, but are usually just used for the type, e.g. in List.toArray.
  void testLengthZero() {
    @NonNull Object @NonNull [] objs;
    objs = new Object[0];
  }

  /* Test case for Issue 153.
  // toArray re-uses the passed array, if it is of appropriate size.
  // It is only guaranteed to be non-null, if it is at most the same size.
  void testToArray(java.util.Set<Object> nns) {
      @NonNull Object [] nna = nns.toArray(new Object[nns.size()]);
      // Given array is too small -> new one is created.
      nna = nns.toArray(new Object[nns.size()-2]);
      // Padding elements will be null.
      // TODO:: error: (assignment)
      nna = nns.toArray(new Object[nns.size() + 2]);
      @Nullable Object [] nbla = nns.toArray(new Object[nns.size() + 2]);
  }
  */

  void testMultiDim() {
    // new double[10][10] has type double @NonNull[] @Nullable[]
    // :: error: (new.array)
    double @NonNull [] @NonNull [] daa = new double[10][10];
    double @NonNull [] @Nullable [] daa2 = new double[10][10];

    // new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
    // :: error: (new.array)
    @Nullable Object @NonNull [] @NonNull [] oaa = new Object[10][10];
    @Nullable Object @NonNull [] @Nullable [] oaa2 = new Object[10][10];

    // new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
    // :: error: (new.array)
    oaa2 = new Object @NonNull [10] @NonNull [10];

    @MonotonicNonNull Object @NonNull [] @MonotonicNonNull [] oaa3 =
        new @MonotonicNonNull Object @NonNull [10] @MonotonicNonNull [10];
    oaa3[0] = new @MonotonicNonNull Object[4];
    // :: error: (assignment)
    oaa3[0] = null;
    // :: error: (assignment) :: error: (accessing.nullable)
    oaa3[0][0] = null;
  }

  @PolyNull Object[] testPolyNull(@PolyNull Object[] in) {
    @PolyNull Object[] out = new @PolyNull Object[in.length];
    for (int i = 0; i < in.length; ++i) {
      if (in[i] == null) {
        out[i] = null;
      } else {
        out[i] = in[i].getClass().toString();
        // :: error: (assignment)
        out[i] = null;
      }
    }
    return out;
  }

  void testMonotonicNonNull() {
    @MonotonicNonNull Object @NonNull [] loa = new @MonotonicNonNull Object @NonNull [10];
    loa = new Object @NonNull [10];
    loa[0] = new Object();
    @MonotonicNonNull Object @NonNull [] loa2 = new Object @NonNull [10];
    // :: error: (dereference.of.nullable)
    loa2[0].toString();
  }

  @MonotonicNonNull Object @NonNull [] testReturnContext() {
    return new Object[10];
  }

  // :: error: (new.array)
  @NonNull Object @NonNull [] oa0 = new Object[10];

  // OK
  @MonotonicNonNull Object @NonNull [] loa0 = new @MonotonicNonNull Object @NonNull [10];

  Object[] oa1 = new Object[] {new Object()};

  // :: error: (assignment)
  Object[] oa2 = new Object[] {new Object(), null};

  public static void main(String[] args) {
    ArrayCreationNullable e = new ArrayCreationNullable();
    Integer[] ints = new Integer[] {5, 6};
    // This would result in a NPE, if there were no error.
    e.testIntegerArray(ints);
  }
}
