import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
import org.checkerframework.checker.lock.qual.*;
import org.checkerframework.dataflow.qual.SideEffectFree;

public class TestTreeKinds {
  class MyClass {
    Object field = new Object();

    @LockingFree
    Object method(@GuardSatisfied MyClass this) {
      return new Object();
    }

    void method2(@GuardSatisfied MyClass this) {}
  }

  @GuardedBy("lock") MyClass m;

  {
    // In constructor/initializer, it's OK not to hold the lock on 'this', but other locks must
    // be respected.
    // :: error: (lock.not.held)
    m.field = new Object();
  }

  final ReentrantLock lock = new ReentrantLock();
  final ReentrantLock lock2 = new ReentrantLock();

  @GuardedBy("lock") MyClass foo = new MyClass();

  MyClass unguardedFoo = new MyClass();

  @EnsuresLockHeld("lock")
  void lockTheLock() {
    lock.lock();
  }

  @EnsuresLockHeld("lock2")
  void lockTheLock2() {
    lock2.lock();
  }

  @EnsuresLockHeldIf(expression = "lock", result = true)
  boolean tryToLockTheLock() {
    return lock.tryLock();
  }

  // This @MayReleaseLocks annotation causes dataflow analysis to assume 'lock' is released after
  // unlockTheLock() is called.
  @MayReleaseLocks
  void unlockTheLock() {}

  @SideEffectFree
  void sideEffectFreeMethod() {}

  @LockingFree
  void lockingFreeMethod() {}

  @MayReleaseLocks
  void nonSideEffectFreeMethod() {}

  @Holding("lock")
  void requiresLockHeldMethod() {}

  MyClass fooArray @GuardedBy("lock") [] = new MyClass[3];

  @GuardedBy("lock") MyClass fooArray2[] = new MyClass[3];

  @GuardedBy("lock") MyClass fooArray3[][] = new MyClass[3][3];

  MyClass fooArray4 @GuardedBy("lock") [][] = new MyClass[3][3];

  MyClass fooArray5[] @GuardedBy("lock") [] = new MyClass[3][3];

  class myClass {
    int i = 0;
  }

  @GuardedBy("lock") myClass myClassInstance = new myClass();

  @GuardedBy("lock") Exception exception = new Exception();

  class MyParametrizedType<T> {
    T foo;
    int l;
  }

  @GuardedBy("lock") MyParametrizedType<MyClass> myParametrizedType = new MyParametrizedType<>();

  MyClass getFooWithWrongReturnType() {
    // :: error: (return)
    return foo; // return of guarded object
  }

  @GuardedBy("lock") MyClass getFoo() {
    return foo;
  }

  MyClass @GuardedBy("lock") [] getFooArray() {
    return fooArray;
  }

  @GuardedBy("lock") MyClass[] getFooArray2() {
    return fooArray2;
  }

  @GuardedBy("lock") MyClass[][] getFooArray3() {
    return fooArray3;
  }

  MyClass @GuardedBy("lock") [][] getFooArray4() {
    return fooArray4;
  }

  MyClass[] @GuardedBy("lock") [] getFooArray5() {
    return fooArray5;
  }

  enum myEnumType {
    ABC,
    DEF
  }

  @GuardedBy("lock") myEnumType myEnum;

  void testEnumType() {
    // TODO: assignment is technically correct, but we could
    // make it friendlier for the user if constant enum values on the RHS
    // automatically cast to the @GuardedBy annotation of the LHS.
    // :: error: (assignment)
    myEnum = myEnumType.ABC;
  }

  final Object intrinsicLock = new Object();

  void testThreadHoldsLock(@GuardedBy("intrinsicLock") MyClass m) {
    if (Thread.holdsLock(intrinsicLock)) {
      m.field.toString();
    } else {
      // :: error: (lock.not.held)
      m.field.toString();
    }
  }

  void testTreeTypes() {
    int i, l;

    MyClass o = new MyClass();
    MyClass f = new MyClass();

    // The following test cases were inspired from annotator.find.ASTPathCriterion.isSatisfiedBy
    // in the Annotation File Utilities

    // TODO: File a bug for the dataflow issue mentioned in the line below.
    // TODO: uncomment: Hits a bug in dataflow:
    // do {
    //     break;
    // } while (foo.field != null); // access to guarded object in condition of do/while loop
    // :: error: (lock.not.held)
    for (foo = new MyClass(); foo.field != null; foo = new MyClass()) {
      break;
    } // access to guarded object in condition of for loop
    // assignment to guarded object (OK) --- foo is still refined to @GuardedBy("lock") after
    // this point, though.
    foo = new MyClass();
    // A simple method call to a guarded object is not considered a dereference (only field
    // accesses are considered dereferences).
    unguardedFoo.method2();
    // Same as above, but the guard must be satisfied if the receiver is @GuardSatisfied.
    // :: error: (lock.not.held)
    foo.method2();
    // attempt to use guarded object in a switch statement
    // :: error: (lock.not.held)
    switch (foo.field.hashCode()) {
    }
    // attempt to use guarded object inside a try with resources
    // try(foo = new MyClass()) { foo.field.toString(); }

    // Retrieving an element from a guarded array is a dereference
    // :: error: (lock.not.held)
    MyClass m = fooArray[0];

    // method call on dereference of unguarded element of *guarded* array
    // :: error: (lock.not.held)
    fooArray[0].field.toString();
    // :: error: (lock.not.held)
    l = fooArray.length; // dereference of guarded array itself

    // method call on dereference of guarded array element
    // :: error: (lock.not.held)
    fooArray2[0].field.toString();
    // method call on dereference of unguarded array - TODO: currently preconditions are not
    // retrieved correctly from array types. This is not unique to the Lock Checker.
    // fooArray2.field.toString();

    // method call on dereference of guarded array element of multidimensional array
    // :: error: (lock.not.held)
    fooArray3[0][0].field.toString();
    // method call on dereference of unguarded single-dimensional array element of unguarded
    // multidimensional array - TODO: currently preconditions are not retrieved correctly from
    // array types. This is not unique to the Lock Checker.
    // fooArray3[0].field.toString();
    // method call on dereference of unguarded multidimensional array - TODO: currently
    // preconditions are not retrieved correctly from array types. This is not unique to the
    // Lock Checker.
    // fooArray3.field.toString();

    // method call on dereference of unguarded array element of *guarded* multidimensional array
    // :: error: (lock.not.held)
    fooArray4[0][0].field.toString();
    // dereference of unguarded single-dimensional array element of *guarded* multidimensional
    // array
    // :: error: (lock.not.held)
    l = fooArray4[0].length;
    // dereference of guarded multidimensional array
    // :: error: (lock.not.held)
    l = fooArray4.length;

    // method call on dereference of unguarded array element of *guarded subarray* of
    // multidimensional array
    // :: error: (lock.not.held)
    fooArray5[0][0].field.toString();
    // dereference of guarded single-dimensional array element of multidimensional array
    // :: error: (lock.not.held)
    l = fooArray5[0].length;
    // dereference of unguarded multidimensional array
    l = fooArray5.length;

    // :: error: (lock.not.held)
    l = getFooArray().length; // dereference of guarded array returned by a method

    // method call on dereference of guarded array element returned by a method
    // :: error: (lock.not.held)
    getFooArray2()[0].field.toString();
    // dereference of unguarded array returned by a method
    l = getFooArray2().length;

    // method call on dereference of guarded array element of multidimensional array returned by
    // a method
    // :: error: (lock.not.held)
    getFooArray3()[0][0].field.toString();
    // dereference of unguarded single-dimensional array element of multidimensional array
    // returned by a method
    l = getFooArray3()[0].length;
    // dereference of unguarded multidimensional array returned by a method
    l = getFooArray3().length;

    // method call on dereference of unguarded array element of *guarded* multidimensional array
    // returned by a method
    // :: error: (lock.not.held)
    getFooArray4()[0][0].field.toString();
    // dereference of unguarded single-dimensional array element of *guarded* multidimensional
    // array returned by a method
    // :: error: (lock.not.held)
    l = getFooArray4()[0].length;
    // dereference of guarded multidimensional array returned by a method
    // :: error: (lock.not.held)
    l = getFooArray4().length;

    // method call on dereference of unguarded array element of *guarded subarray* of
    // multidimensional array returned by a method
    // :: error: (lock.not.held)
    getFooArray5()[0][0].field.toString();
    // dereference of guarded single-dimensional array element of multidimensional array
    // returned by a method
    // :: error: (lock.not.held)
    l = getFooArray5()[0].length;
    // dereference of unguarded multidimensional array returned by a method
    l = getFooArray5().length;

    // Test different @GuardedBy(...) present on the element and array locations.
    @GuardedBy("lock") MyClass @GuardedBy("lock2") [] array = new MyClass[3];
    // :: error: (lock.not.held)
    array[0].field = new Object();
    if (lock.isHeldByCurrentThread()) {
      // :: error: (lock.not.held)
      array[0].field = new Object();
      if (lock2.isHeldByCurrentThread()) {
        array[0].field = new Object();
      }
    }

    // method call on guarded object within parenthesized expression
    // :: error: (lock.not.held)
    String s = (foo.field.toString());
    // :: error: (lock.not.held)
    foo.field.toString(); // method call on guarded object
    // :: error: (lock.not.held)
    getFoo().field.toString(); // method call on guarded object returned by a method
    // :: error: (lock.not.held)
    this.foo.field.toString(); // method call on guarded object using 'this' literal
    // dereference of guarded object in labeled statement
    label:
    // :: error: (lock.not.held)
    foo.field.toString();
    // access to guarded object in instanceof expression (OK)
    if (foo instanceof MyClass) {}
    // access to guarded object in while condition of while loop (OK)
    while (foo != null) {
      break;
    }
    // binary operator on guarded object in else if condition (OK)
    if (false) {
    } else if (foo == o) {
    }
    // access to guarded object in a lambda expression
    Runnable rn =
        () -> {
          // :: error: (lock.not.held)
          foo.field.toString();
        };
    // :: error: (lock.not.held)
    i = myClassInstance.i; // access to member field of guarded object
    // MemberReferenceTrees? how do they work
    fooArray = new MyClass[3]; // second allocation of guarded array (OK)
    // dereference of guarded object in conditional expression tree
    // :: error: (lock.not.held)
    s = i == 5 ? foo.field.toString() : f.field.toString();
    // dereference of guarded object in conditional expression tree
    // :: error: (lock.not.held)
    s = i == 5 ? f.field.toString() : foo.field.toString();
    // Testing of 'return' is done in getFooWithWrongReturnType()
    // throwing a guarded object - when throwing an exception, it must be @GuardedBy({}). Even
    // @GuardedByUnknown is not allowed.
    try {
      // :: error: (throw)
      throw exception;
    } catch (Exception e) {
    }
    // casting of a guarded object to an unguarded object
    // :: error: (assignment)
    @GuardedBy({}) Object e1 = (Object) exception;
    // OK, since the local variable's type gets refined to @GuardedBy("lock")
    Object e2 = (Object) exception;
    // :: error: (lock.not.held)
    l = myParametrizedType.l; // dereference of guarded object having a parameterized type

    // We need to support locking on local variables and protecting local variables because
    // these locals may contain references to fields. Somehow we need to pass along the
    // information of which field it was.

    if (foo == o) { // binary operator on guarded object (OK)
      o.field.toString();
    }

    if (foo == null) {
      // With -AconcurrentSemantics turned off, a cannot.dereference error would be expected,
      // since there is an attempt to dereference an expression whose type has been refined to
      // @GuardedByBottom (due to the comparison to null). However, with -AconcurrentSemantics
      // turned on, foo may no longer be null by now, the refinement to @GuardedByBottom is
      // lost and the refined type of foo is now the declared type ( @GuardedBy("lock") ),
      // resulting in the lock.not.held error.
      // :: error: (lock.not.held)
      foo.field.toString();
    }

    // TODO: Reenable:
    // @PolyGuardedBy should not be written here, but it is not explicitly forbidden by the
    // framework.
    // @PolyGuardedBy MyClass m2 = new MyClass();
    // (cannot.dereference)
    // m2.field.toString();
  }

  @MayReleaseLocks
  public void testLocals() {
    final ReentrantLock localLock = new ReentrantLock();

    @GuardedBy("localLock") MyClass guardedByLocalLock = new MyClass();

    // :: error: (lock.not.held)
    guardedByLocalLock.field.toString();

    @GuardedBy("lock") MyClass local = new MyClass();

    // :: error: (lock.not.held)
    local.field.toString();

    lockTheLock();

    local.field.toString(); // No warning output

    unlockTheLock();
  }

  @MayReleaseLocks
  public void testMethodAnnotations() {
    Random r = new Random();

    if (r.nextBoolean()) {
      lockTheLock();
      requiresLockHeldMethod();
    } else {
      // :: error: (contracts.precondition)
      requiresLockHeldMethod();
    }

    if (r.nextBoolean()) {
      lockTheLock();
      foo.field.toString();

      unlockTheLock();

      // :: error: (lock.not.held)
      foo.field.toString();
    } else {
      // :: error: (lock.not.held)
      foo.field.toString();
    }

    if (tryToLockTheLock()) {
      foo.field.toString();
    } else {
      // :: error: (lock.not.held)
      foo.field.toString();
    }

    if (r.nextBoolean()) {
      lockTheLock();
      sideEffectFreeMethod();
      foo.field.toString();
    } else {
      lockTheLock();
      nonSideEffectFreeMethod();
      // :: error: (lock.not.held)
      foo.field.toString();
    }

    if (r.nextBoolean()) {
      lockTheLock();
      lockingFreeMethod();
      foo.field.toString();
    } else {
      lockTheLock();
      nonSideEffectFreeMethod();
      // :: error: (lock.not.held)
      foo.field.toString();
    }
  }

  void methodThatTakesAnInteger(Integer i) {}

  void testBoxedPrimitiveType() {
    Integer i = null;
    if (i == null) {}

    methodThatTakesAnInteger(i);
  }

  void testReceiverGuardedByItself(@GuardedBy("<self>") TestTreeKinds this) {
    // :: error: (lock.not.held)
    method();
    synchronized (this) {
      method();
    }
  }

  void method(@GuardSatisfied TestTreeKinds this) {}

  void testOtherClassReceiverGuardedByItself(final @GuardedBy("<self>") OtherClass o) {
    // :: error: (lock.not.held)
    o.foo();
    synchronized (o) {
      o.foo();
    }
  }

  class OtherClass {
    void foo(@GuardSatisfied OtherClass this) {}
  }

  void testExplicitLockSynchronized() {
    final ReentrantLock lock = new ReentrantLock();
    // :: error: (explicit.lock.synchronized)
    synchronized (lock) {
    }
  }

  void testPrimitiveTypeGuardedby() {
    // :: error: (immutable.type.guardedby)
    @GuardedBy("lock") int a = 0;
    // :: error: (immutable.type.guardedby)
    @GuardedBy int b = 0;
    // :: error: (immutable.type.guardedby) :: error: (guardsatisfied.location.disallowed)
    @GuardSatisfied int c = 0;
    // :: error: (immutable.type.guardedby) :: error: (guardsatisfied.location.disallowed)
    @GuardSatisfied(1) int d = 0;
    int e = 0;
    // :: error: (immutable.type.guardedby)
    @GuardedByUnknown int f = 0;
    // :: error: (immutable.type.guardedby) :: error: (assignment)
    @GuardedByBottom int g = 0;
  }

  void testBinaryOperatorBooleanResultIsAlwaysGuardedByNothing() {
    @GuardedBy("lock") Object o1 = new Object();
    Object o2 = new Object();
    // boolean variables are implicitly @GuardedBy({}).
    boolean b1 = o1 == o2;
    boolean b2 = o2 == o1;
    boolean b3 = o1 != o2;
    boolean b4 = o2 != o1;
    boolean b5 = o1 instanceof Object;
    boolean b6 = o2 instanceof Object;
    boolean b7 = o1 instanceof @GuardedBy("lock") Object;
    boolean b8 = o2 instanceof @GuardedBy("lock") Object;
  }
}
