// 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.naming.applymapping.sourcelibrary;

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

import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.naming.applymapping.shared.NoMappingDumps.HasMappingDump;
import com.android.tools.r8.naming.applymapping.shared.NoMappingDumps.NoMappingDump;
import com.android.tools.r8.naming.applymapping.shared.NoMappingDumps.NoMappingMainDump;
import com.android.tools.r8.naming.applymapping.shared.SwappingDump.ADump;
import com.android.tools.r8.naming.applymapping.shared.SwappingDump.BDump;
import com.android.tools.r8.naming.applymapping.shared.SwappingDump.MainDump;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class MemberResolutionAsmTest extends TestBase {
  private final TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public MemberResolutionAsmTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  //  class HasMapping { // : X
  //    HasMapping() {
  //      foo();
  //    }
  //
  //    void foo() { // : a
  //      System.out.println("HasMapping#foo");
  //    }
  //  }
  //
  //  class NoMapping extends HasMapping { // : Y
  //    NoMapping() {
  //      super();
  //      foo();
  //    }
  //
  //    private void foo() { // no mapping
  //      System.out.println("NoMapping#foo");
  //    }
  //  }
  //
  //  class NoMappingMain {
  //    public static void main(String[] args) {
  //      new NoMapping();
  //    }
  //  }
  private final String noMappingMain = "NoMappingMain";
  private final String noMappingExpected = StringUtils.lines("HasMapping#foo", "NoMapping#foo");

  private List<byte[]> noMappingInputs() throws Exception {
    return ImmutableList.of(HasMappingDump.dump(), NoMappingDump.dump(), NoMappingMainDump.dump());
  }

  @Test
  public void testNoMappingReference() throws Exception {
    testForRuntime(parameters)
        .addProgramClassFileData(noMappingInputs())
        .run(parameters.getRuntime(), noMappingMain)
        .assertSuccessWithOutput(noMappingExpected);
  }

  @Test
  public void testNoMappingR8() throws Exception {
    String pgMap =
        StringUtils.joinLines(
            "# Long comment to avoid reformatting of the lines below.",
            "HasMapping -> X:",
            "  void foo() -> a",
            "NoMapping -> Y:"
            // Intentionally missing a mapping for `private` foo().
            );

    CodeInspector codeInspector =
        testForR8(parameters.getBackend())
            .addProgramClassFileData(noMappingInputs())
            .setMinApi(parameters.getApiLevel())
            .addKeepMainRule(noMappingMain)
            .addApplyMapping(pgMap)
            .addOptionsModification(
                options -> {
                  options.inlinerOptions().enableInlining = false;
                  options.enableVerticalClassMerging = false;
                })
            .run(parameters.getRuntime(), noMappingMain)
            .assertSuccessWithOutput(noMappingExpected)
            .inspector();

    ClassSubject base = codeInspector.clazz("HasMapping");
    assertThat(base, isPresentAndRenamed());
    assertEquals("X", base.getFinalName());
    MethodSubject x = base.method("void", "foo", ImmutableList.of());
    assertThat(x, isPresentAndRenamed());
    assertEquals("a", x.getFinalName());

    // To ensure still getting illegal-access error we need to rename consistently.
    ClassSubject sub = codeInspector.clazz("NoMapping");
    assertThat(sub, isPresentAndRenamed());
    assertEquals("Y", sub.getFinalName());
    MethodSubject y = sub.method("void", "a", ImmutableList.of());
    assertThat(y, isPresent());
  }

  //  class A { // : X
  //    A() {
  //      x();
  //      y();
  //    }
  //
  //    private void x() { // : y
  //      System.out.println("A#x");
  //    }
  //
  //    public void y() { // : x
  //      System.out.println("A#y");
  //    }
  //  }
  //
  //  class B extends A { // : Y
  //  }
  //
  //  class Main {
  //    public static void main(String[] args) {
  //      new B().x(); // IllegalAccessError
  //    }
  //  }
  private final String swappingMain = "Main";

  private List<byte[]> swappingInputs() throws Exception {
    return ImmutableList.of(ADump.dump(), BDump.dump(), MainDump.dump());
  }

  private String getMethodSignature(String type, String method) {
    if (parameters.isCfRuntime()) {
      return parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
          ? ("void " + type + "." + method + "()")
          : (type + "." + method + "()V");
    }
    assert parameters.isDexRuntime();
    Version version = parameters.getRuntime().asDex().getVm().getVersion();
    if (version.isOlderThanOrEqual(Version.V4_4_4)) {
      return "L" + type + ";." + method + " ()V";
    }
    return "void " + type + "." + method + "()";
  }

  @Test
  public void testSwappingReference() throws Exception {
    testForRuntime(parameters)
        .addProgramClassFileData(swappingInputs())
        .run(parameters.getRuntime(), swappingMain)
        .assertFailureWithErrorThatThrows(IllegalAccessError.class)
        .assertFailureWithErrorThatMatches(containsString(getMethodSignature("A", "x")));
  }

  @Test
  public void testSwappingR8() throws Exception {
    String pgMap =
        StringUtils.joinLines(
            "# Long comment to avoid reformatting of the lines below.",
            "A -> X:",
            "  void x() -> y",
            "  void y() -> x",
            "B -> Y:"
            // Intentionally missing mappings for non-overridden members
            );

    R8TestCompileResult compileResult =
        testForR8(parameters.getBackend())
            .setMinApi(parameters.getApiLevel())
            .addProgramClassFileData(swappingInputs())
            .addKeepMainRule(swappingMain)
            .addApplyMapping(pgMap)
            .addOptionsModification(
                options -> {
                  options.inlinerOptions().enableInlining = false;
                  options.enableVerticalClassMerging = false;
                })
            .compile();

    compileResult
        .run(parameters.getRuntime(), swappingMain)
        .assertFailureWithErrorThatThrows(IllegalAccessError.class);

    CodeInspector codeInspector = compileResult.inspector();
    ClassSubject base = codeInspector.clazz("A");
    assertThat(base, isPresentAndRenamed());
    assertEquals("X", base.getFinalName());
    MethodSubject x = base.method("void", "x", ImmutableList.of());
    assertThat(x, isPresentAndRenamed());
    assertEquals("y", x.getFinalName());

    ClassSubject sub = codeInspector.clazz("B");
    assertThat(sub, isPresentAndRenamed());
    assertEquals("Y", sub.getFinalName());
    MethodSubject subX = sub.method("void", "x", ImmutableList.of());
    assertThat(subX, not(isPresent()));
  }
}
