// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.regress.b111250398;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.code.Iget;
import com.android.tools.r8.code.IgetObject;
import com.android.tools.r8.code.Sget;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import org.junit.Test;

// Copy of javax.inject.Provider.
interface Provider<T> {
  T get();
}

// Copy of dagger.internal.SingleClass.
final class SingleCheck<T> implements Provider<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private SingleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the delegate provider
  @Override
  public T get() {
    Object local = instance;
    if (local == UNINITIALIZED) {
      // provider is volatile and might become null after the check, so retrieve the provider first
      Provider<T> providerReference = provider;
      if (providerReference == null) {
        // The provider was null, so the instance must already be set
        local = instance;
      } else {
        local = providerReference.get();
        instance = local;

        // Null out the reference to the provider. We are never going to need it again, so we can
        // make it eligible for GC.
        provider = null;
      }
    }
    return (T) local;
  }

  // This method is not relevant for the test.
  /*
  public static <P extends Provider<T>, T> Provider<T> provider(P provider) {
    // If a scoped @Binds delegates to a scoped binding, don't cache the value again.
    if (provider instanceof SingleCheck || provider instanceof DoubleCheck) {
      return provider;
    }
    return new SingleCheck<T>(checkNotNull(provider));
  }
  */
}

// Several field gets on non-volatile and volatile fields on the same class.
class A {
  int t;
  int f;
  static int sf;
  volatile int v;
  static volatile int sv;

  public void mf() {
    t = f;
    t = f;
    t = f;
    t = f;
    t = f;
  }

  public void mfWithMonitor() {
    t = f;
    synchronized (this) {
      t = f;
      t = f;
    }
    t = f;
    t = f;
  }

  public void msf() {
    t = sf;
    t = sf;
    t = sf;
    t = sf;
    t = sf;
  }

  public void mv() {
    t = v;
    t = v;
    t = v;
    t = v;
    t = v;
  }

  public void msv() {
    t = sv;
    t = sv;
    t = sv;
    t = sv;
    t = sv;
  }
}

// Several field gets on non-volatile and volatile fields on different class.
class B {
  int t;

  public void mf(A a) {
    t = a.f;
    t = a.f;
    t = a.f;
    t = a.f;
    t = a.f;
  }

  public void msf() {
    t = A.sf;
    t = A.sf;
    t = A.sf;
    t = A.sf;
    t = A.sf;
  }

  public void mv(A a) {
    t = a.v;
    t = a.v;
    t = a.v;
    t = a.v;
    t = a.v;
  }

  public void msv() {
    t = A.sv;
    t = A.sv;
    t = A.sv;
    t = A.sv;
    t = A.sv;
  }
}

// Modified sample from http://tutorials.jenkov.com/java-concurrency/volatile.html.
class C {
  private int years;
  private int months;
  private volatile int days;

  public int totalDays() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public int totalDaysTimes2() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public int totalDaysTimes3() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public void update(int years, int months, int days){
    this.years  = years;
    this.months = months;
    this.days   = days;
  }
}

public class B111250398 extends TestBase {

  private void releaseMode(InternalOptions options) {
    options.debug = false;
  }

  private long countIget(DexCode code, DexField field) {
    return Arrays.stream(code.instructions)
        .filter(instruction -> instruction instanceof Iget)
        .map(instruction -> (Iget) instruction)
        .filter(get -> get.getField() == field)
        .count();
  }

  private long countSget(DexCode code, DexField field) {
    return Arrays.stream(code.instructions)
        .filter(instruction -> instruction instanceof Sget)
        .map(instruction -> (Sget) instruction)
        .filter(get -> get.getField() == field)
        .count();
  }

  private long countIgetObject(MethodSubject method, FieldSubject field) {
    return Arrays.stream(method.getMethod().getCode().asDexCode().instructions)
        .filter(instruction -> instruction instanceof IgetObject)
        .map(instruction -> (IgetObject) instruction)
        .filter(get -> get.getField() == field.getField().field)
        .count();
  }

  private void check(CodeInspector inspector, int mfOnBGets, int msfOnBGets) {
    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());
    MethodSubject mfOnA = classA.method("void", "mf", ImmutableList.of());
    assertThat(mfOnA, isPresent());
    MethodSubject mfWithMonitorOnA = classA.method("void", "mfWithMonitor", ImmutableList.of());
    assertThat(mfWithMonitorOnA, isPresent());
    MethodSubject msfOnA = classA.method("void", "msf", ImmutableList.of());
    assertThat(msfOnA, isPresent());
    MethodSubject mvOnA = classA.method("void", "mv", ImmutableList.of());
    assertThat(mvOnA, isPresent());
    MethodSubject msvOnA = classA.method("void", "msv", ImmutableList.of());
    assertThat(msvOnA, isPresent());
    FieldSubject fOnA = classA.field("int", "f");
    assertThat(fOnA, isPresent());
    FieldSubject sfOnA = classA.field("int", "sf");
    assertThat(sfOnA, isPresent());
    FieldSubject vOnA = classA.field("int", "v");
    assertThat(vOnA, isPresent());
    FieldSubject svOnA = classA.field("int", "sv");
    assertThat(svOnA, isPresent());
    ClassSubject classB = inspector.clazz(B.class);
    assertThat(classB, isPresent());
    MethodSubject mfOnB = classB.method("void", "mf", ImmutableList.of(classA.getOriginalName()));
    assertThat(mfOnB, isPresent());
    MethodSubject msfOnB = classB.method("void", "msf", ImmutableList.of());
    assertThat(msfOnB, isPresent());
    MethodSubject mvOnB = classB.method("void", "mv", ImmutableList.of(classA.getOriginalName()));
    assertThat(mvOnB, isPresent());
    MethodSubject msvOnB = classB.method("void", "msv", ImmutableList.of());
    assertThat(msvOnB, isPresent());
    // Field load of volatile fields are never eliminated.
    assertEquals(5, countIget(mvOnA.getMethod().getCode().asDexCode(), vOnA.getField().field));
    assertEquals(5, countSget(msvOnA.getMethod().getCode().asDexCode(), svOnA.getField().field));
    assertEquals(5, countIget(mvOnB.getMethod().getCode().asDexCode(), vOnA.getField().field));
    assertEquals(5, countSget(msvOnB.getMethod().getCode().asDexCode(), svOnA.getField().field));
    // For fields on the same class both separate compilation (D8) and whole program
    // compilation (R8) will eliminate field loads on non-volatile fields.
    assertEquals(1, countIget(mfOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
    assertEquals(1, countSget(msfOnA.getMethod().getCode().asDexCode(), sfOnA.getField().field));
    assertEquals(
        2, countIget(mfWithMonitorOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));

    // For fields on other class both separate compilation (D8) and whole program
    // compilation (R8) will differ in the eliminated field loads of non-volatile fields.
    assertEquals(mfOnBGets,
        countIget(mfOnB.getMethod().getCode().asDexCode(), fOnA.getField().field));
    assertEquals(msfOnBGets,
        countSget(msfOnB.getMethod().getCode().asDexCode(), sfOnA.getField().field));
  }

  @Test
  public void testSeparateCompilation() throws Exception {
    CodeInspector inspector =
        new CodeInspector(compileWithD8(readClasses(A.class, B.class), this::releaseMode));
    check(inspector, 5, 5);
  }

  @Test
  public void testWholeProgram() throws Exception {
    CodeInspector inspector =
        new CodeInspector(compileWithR8(readClasses(A.class, B.class), this::releaseMode));
    check(inspector, 1, 1);
  }

  private void checkMixed(AndroidApp app) throws Exception{
    CodeInspector inspector = new CodeInspector(app);
    ClassSubject classC = inspector.clazz(C.class);
    assertThat(classC, isPresent());
    MethodSubject totalDays = classC.method("int", "totalDays", ImmutableList.of());
    assertThat(totalDays, isPresent());
    MethodSubject totalDaysTimes2 = classC.method("int", "totalDaysTimes2", ImmutableList.of());
    assertThat(totalDaysTimes2, isPresent());
    MethodSubject totalDaysTimes3 = classC.method("int", "totalDaysTimes3", ImmutableList.of());
    assertThat(totalDaysTimes3, isPresent());
    FieldSubject years = classC.field("int", "years");
    assertThat(years, isPresent());
    FieldSubject months = classC.field("int", "months");
    assertThat(months, isPresent());
    FieldSubject days = classC.field("int", "days");
    assertThat(days, isPresent());


    for (FieldSubject field : new FieldSubject[]{years, months, days}) {
      assertEquals(1,
          countIget(totalDays.getMethod().getCode().asDexCode(), field.getField().field));
      assertEquals(2,
          countIget(totalDaysTimes2.getMethod().getCode().asDexCode(), field.getField().field));
      assertEquals(3,
          countIget(totalDaysTimes3.getMethod().getCode().asDexCode(), field.getField().field));
    }
  }

  @Test
  public void testMixedVolatileNonVolatile() throws Exception {
    AndroidApp app = readClasses(C.class);
    checkMixed(compileWithD8(app, this::releaseMode));
    checkMixed(compileWithR8(app, this::releaseMode));
  }

  private void checkDaggerSingleProviderGet(AndroidApp app) throws Exception {
    CodeInspector inspector = new CodeInspector(app);
    MethodSubject get =
        inspector.clazz(SingleCheck.class).method("java.lang.Object", "get", ImmutableList.of());
    assertThat(get, isPresent());
    FieldSubject instance =
        inspector.clazz(SingleCheck.class).field("java.lang.Object", "instance");
    assertEquals(2, countIgetObject(get, instance));
  }

  @Test
  public void testDaggerSingleProvider() throws Exception {
    AndroidApp app = readClasses(Provider.class, SingleCheck.class);
    checkDaggerSingleProviderGet(compileWithD8(app, this::releaseMode));
    checkDaggerSingleProviderGet(compileWithR8(app, this::releaseMode));
  }
}
