// 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.accessrelaxation;

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

import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class L1 {
  private final String x;

  private L1(String x) {
    this.x = x;
  }

  private L1() {
    this("private_x");
  }

  static L1 create() {
    return new L1();
  }

  L1(int i) {
    this(String.valueOf(i));
  }

  @Override
  public String toString() {
    return x;
  }
}

class L2_1 extends L1 {
  private String y;

  private L2_1() {
    this(21);
    this.y = "private_L2_1_y";
  }

  L2_1(int i) {
    super(i);
    this.y = "L2_1_y";
  }

  private L2_1(String y) {
    this(21);
    this.y = y;
  }

  static L2_1 create(String y) {
    return new L2_1(y);
  }

  @Override
  public String toString() {
    return super.toString() + "_" + y;
  }
}

class L2_2 extends L1 {
  private String y;

  private L2_2(int i) {
    super(i);
    this.y = "private_L2_2_y";
  }

  L2_2(String y) {
    this(22);
    this.y = y;
  }

  static L2_1 create() {
    return new L2_1(22);
  }

  @Override
  public String toString() {
    return super.toString() + "_" + y;
  }
}

class L3_1 extends L2_1 {
  private final String z;

  private L3_1(int i) {
    this(String.valueOf(i));
  }

  private L3_1(String z) {
    super(31);
    this.z = z;
  }

  static L3_1 create(int i) {
    return new L3_1(i);
  }

  @Override
  public String toString() {
    return super.toString() + "_" + z;
  }
}

class L3_2 extends L2_2 {
  private String z;

  private L3_2() {
    super("private_L3_2_y");
    this.z = "private_L3_2_z";
  }

  private L3_2(int i) {
    super(String.valueOf(i));
    this.z = "private_L3_2_z" + "_" + i;
  }

  L3_2(String z) {
    this(32);
    this.z = z;
  }

  static L3_2 create(String z) {
    return new L3_2(z);
  }

  @Override
  public String toString() {
    return super.toString() + "_" + z;
  }
}

class CtorTestMain {
  public static void main(String[] args) {
    System.out.println(L1.create());
    System.out.println(L2_1.create("main_y"));
    System.out.println(L2_2.create());
    System.out.println(L3_1.create(41));
    System.out.println(L3_2.create("main_z"));
  }
}

@RunWith(Parameterized.class)
public final class ConstructorRelaxationTest extends AccessRelaxationTestBase {
  private static final String INIT= "<init>";
  private static final List<Class> CLASSES =
      ImmutableList.of(L1.class, L2_1.class, L2_2.class, L3_1.class, L3_2.class);

  @Parameterized.Parameters(name = "Backend: {0}")
  public static Backend[] data() {
    return Backend.values();
  }

  public ConstructorRelaxationTest(Backend backend) {
    super(backend);
  }

  @Test
  public void test() throws Exception {
    Class mainClass = CtorTestMain.class;
    R8Command.Builder builder =
        loadProgramFiles(backend, Iterables.concat(CLASSES, ImmutableList.of(mainClass)));
    builder.addProguardConfiguration(
        ImmutableList.of(
            "-keep class " + mainClass.getCanonicalName() + "{",
            "  public static void main(java.lang.String[]);",
            "}",
            "",
            "-keep class *.L* {",
            "  <init>(...);",
            "}",
            "",
            "-dontobfuscate",
            "-allowaccessmodification"
        ),
        Origin.unknown());

    AndroidApp app =
        ToolHelper.runR8(
            builder.build(),
            options -> {
              options.enableInlining = false;
              options.enableVerticalClassMerging = false;
            });
    compareReferenceJVMAndProcessed(app, mainClass);

    CodeInspector codeInspector = new CodeInspector(app);
    for (Class clazz : CLASSES) {
      ClassSubject classSubject = codeInspector.clazz(clazz);
      assertThat(classSubject, isPresent());
      classSubject.getDexClass().forEachMethod(m -> {
        assertTrue(!m.isInstanceInitializer() || m.isPublicMethod());
      });
    }
  }

}
