// Copyright (c) 2021, 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.memberrebinding;

import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static java.util.Collections.emptyList;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Collection;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class LibraryMemberRebindingInterfaceTest extends TestBase {

  private static Path oldRuntimeJar;
  private static Path newRuntimeJar;

  @Parameter(0)
  public TestParameters parameters;

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

  @BeforeClass
  public static void compileCustomLib() throws Exception {
    oldRuntimeJar =
        createJar(
            ImmutableList.of(LibraryI.class, LibraryB.class, LibraryC.class),
            getProgramClassFileDataWithoutMethods(LibraryA.class));
    newRuntimeJar =
        createJar(ImmutableList.of(LibraryI.class, LibraryA.class, LibraryB.class, LibraryC.class));
  }

  // Tests old android.jar with old runtime.
  @Test
  public void testEmptyAAtCompileTimeAndRuntime() throws Exception {
    test(oldRuntimeJar, oldRuntimeJar);
  }

  // Tests new android.jar with new runtime.
  @Test
  public void testNonEmptyAAtCompileTimeAndRuntime() throws Exception {
    test(newRuntimeJar, newRuntimeJar);
  }

  // Tests old android.jar with new runtime.
  @Test
  public void testEmptyAAtCompileTime() throws Exception {
    test(oldRuntimeJar, newRuntimeJar);
  }

  // Tests new android.jar with old runtime.
  @Test
  public void testEmptyAAtRuntimeTime() throws Exception {
    test(newRuntimeJar, oldRuntimeJar);
  }

  private void test(Path compileTimeLibrary, Path runtimeLibrary) throws Exception {
    Method m = LibraryI.class.getDeclaredMethod("m");
    MethodReference methodReferenceForM = Reference.methodFromMethod(m);
    testForR8(parameters.getBackend())
        .addProgramClasses(Main.class)
        .addKeepClassAndMembersRules(Main.class)
        .addLibraryFiles(compileTimeLibrary)
        .addDefaultRuntimeLibrary(parameters)
        .apply(setMockApiLevelForMethod(m, AndroidApiLevel.B))
        // The api database needs to have an api level for each target, so even though B do not
        // define 'm', we still give it an API level.
        .apply(
            setMockApiLevelForMethod(
                Reference.method(
                    Reference.classFromClass(LibraryB.class),
                    methodReferenceForM.getMethodName(),
                    methodReferenceForM.getFormalTypes(),
                    methodReferenceForM.getReturnType()),
                AndroidApiLevel.B))
        .apply(setMockApiLevelForMethod(LibraryC.class.getDeclaredMethod("m"), AndroidApiLevel.B))
        .apply(setMockApiLevelForMethod(LibraryA.class.getDeclaredMethod("m"), AndroidApiLevel.N))
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              MethodSubject testMethodSubject =
                  inspector.clazz(Main.class).uniqueMethodWithName("test");
              assertThat(testMethodSubject, isPresent());
              assertThat(
                  testMethodSubject,
                  invokesMethod(
                      "int",
                      getExpectedMemberRebindingTarget(compileTimeLibrary).getTypeName(),
                      "m",
                      emptyList()));
            })
        .addRunClasspathFiles(buildOnDexRuntime(parameters, runtimeLibrary))
        .run(parameters.getRuntime(), Main.class)
        .applyIf(
            // Compiling to an API level above the API where LibraryA.m() was defined with a new
            // android.jar, and running this on an older runtime (correctly) results in a NSME.
            parameters.isDexRuntime()
                && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
                && compileTimeLibrary == newRuntimeJar
                && runtimeLibrary == oldRuntimeJar,
            runResult -> runResult.assertFailureWithErrorThatThrows(NoSuchMethodError.class),
            runResult -> runResult.assertSuccessWithOutputLines("42"));
  }

  private Class<?> getExpectedMemberRebindingTarget(Path compileTimeLibrary) {
    if (compileTimeLibrary == newRuntimeJar) {
      // If we are compiling to a new runtime with a new android.jar, we should rebind to LibraryA.
      if (parameters.isDexRuntime()
          && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)) {
        return LibraryA.class;
      }
      // If we are compiling to an old runtime with a new android.jar, we should rebind to LibraryB.
      return LibraryB.class;
    }
    // Otherwise, we are compiling to an old android.jar, in which case we should rebind to
    // LibraryI.
    return LibraryI.class;
  }

  private static Path createJar(Collection<Class<?>> programClasses, byte[]... programClassFileData)
      throws Exception {
    return testForR8(getStaticTemp(), Backend.CF)
        .addProgramClasses(programClasses)
        .addProgramClassFileData(programClassFileData)
        .addKeepAllClassesRule()
        .compile()
        .writeToZip();
  }

  private static byte[] getProgramClassFileDataWithoutMethods(Class<?> clazz) throws IOException {
    return transformer(clazz)
        .removeMethods(
            (int access, String name, String descriptor, String signature, String[] exceptions) ->
                !name.equals("<init>"))
        .transform();
  }

  public static class Main {

    public static void main(String[] args) {
      test(new LibraryC());
    }

    private static void test(LibraryB b) {
      System.out.println(b.m());
    }
  }

  public interface LibraryI {

    int m();
  }

  public static class LibraryA {

    // Added in API N, so we can't rebind to this in APIs < N.
    public int m() {
      return 42;
    }
  }

  public abstract static class LibraryB extends LibraryA implements LibraryI {}

  public static class LibraryC extends LibraryB {

    @Override
    public int m() {
      return 42;
    }
  }
}
