// Copyright (c) 2022, 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.desugar.desugaredlibrary;

import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;

import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;
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;

// Test of an API which is to be treated as a platform API. This is simulating an API which can be
// implemented by an OEM in an on-device APK containing the DEX code. The program will probe for the
// OEM class and if not found it will use a built-in program class implementing the interface.
//
// This is tested with and without library desugaring.

// For context see b/229793269.
@RunWith(Parameterized.class)
public class PseudoPlatformApiTest extends DesugaredLibraryTestBase {

  @Parameter(0)
  public TestParameters parameters;

  @Parameter(1)
  public LibraryDesugaringSpecification libraryDesugaringSpecification;

  @Parameters(name = "{0}, spec: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters()
            .withDexRuntimes()
            .withApiLevelsStartingAtIncluding(AndroidApiLevel.P)
            .build(),
        getJdk8Jdk11());
  }

  private Path androidJarAdditions() throws Exception {
    return ZipBuilder.builder(temp.newFile("additions_android.jar").toPath())
        .addFilesRelative(
            ToolHelper.getClassPathForTests(),
            ToolHelper.getClassFileForTestClass(PseudoPlatformInterface.class))
        .build();
  }

  private Path androidJarAdditionsDex() throws Exception {
    // Build the OEM DEX files without library desugaring enabled and using min API 28.
    return testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addProgramClasses(PseudoPlatformInterface.class)
        .setMinApi(AndroidApiLevel.B)
        .compile()
        .writeToZip();
  }

  private Path oemDex() throws Exception {
    // Build the OEM DEX files without library desugaring enabled and using min API 28.
    return testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        // This is equivalent to adding the PseudoPlatformInterface to android.jar.
        .addLibraryClasses(PseudoPlatformInterface.class)
        .addProgramClasses(OemClass.class)
        .setMinApi(AndroidApiLevel.P)
        .compile()
        .writeToZip();
  }

  @Test
  public void testD8WithoutLibraryDesugaringOemClassNotPresent() throws Exception {
    testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addLibraryFiles(androidJarAdditions())
        .addProgramClasses(ProgramClass.class)
        .setMinApi(AndroidApiLevel.H_MR2)
        .addRunClasspathFiles(androidJarAdditionsDex())
        .run(parameters.getRuntime(), ProgramClass.class)
        .assertSuccessWithOutputLines("DEFAULT-X", "Y-DEFAULT");
  }

  @Test
  public void testD8WithoutLibraryDesugaringOemClassPresent() throws Exception {
    testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addLibraryFiles(androidJarAdditions())
        .addProgramClasses(ProgramClass.class)
        .setMinApi(AndroidApiLevel.H_MR2)
        .addRunClasspathFiles(androidJarAdditionsDex())
        .addRunClasspathFiles(oemDex())
        .run(parameters.getRuntime(), ProgramClass.class)
        .assertSuccessWithOutputLines("OEM-X", "Y-OEM");
  }

  @Test
  public void testD8WithLibraryDesugaringOemClassNotPresent() throws Exception {
    // Enable library desugaring with an effective min API of 1.
    testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addLibraryFiles(androidJarAdditions())
        .addProgramClasses(ProgramClass.class)
        .setMinApi(AndroidApiLevel.H_MR2)
        .enableCoreLibraryDesugaring(
            LibraryDesugaringTestConfiguration.forSpecification(
                libraryDesugaringSpecification.getSpecification()))
        .addRunClasspathFiles(androidJarAdditionsDex())
        .addRunClasspathFiles(
            getNonShrunkDesugaredLib(
                AndroidApiLevel.H_MR2, parameters.getBackend(), libraryDesugaringSpecification))
        .run(parameters.getRuntime(), ProgramClass.class)
        .assertSuccessWithOutputLines("DEFAULT-X", "Y-DEFAULT");
  }

  @Test
  public void testD8WithLibraryDesugaringOemClassPresent() throws Exception {
    // Enable library desugaring with an effective min API of 1.
    testForD8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addLibraryFiles(androidJarAdditions())
        .addProgramClasses(ProgramClass.class)
        .setMinApi(AndroidApiLevel.H_MR2)
        .enableCoreLibraryDesugaring(
            LibraryDesugaringTestConfiguration.forSpecification(
                libraryDesugaringSpecification.getSpecification()))
        .addRunClasspathFiles(androidJarAdditionsDex())
        .addRunClasspathFiles(oemDex())
        .addRunClasspathFiles(
            getNonShrunkDesugaredLib(
                AndroidApiLevel.H_MR2, parameters.getBackend(), libraryDesugaringSpecification))
        .run(parameters.getRuntime(), ProgramClass.class)
        .assertSuccessWithOutputLines("OEM-X", "Y-OEM");
  }

  interface PseudoPlatformInterface {
    Function<String, String> api(Function<String, String> fn);
  }

  static class OemClass implements PseudoPlatformInterface {
    public Function<String, String> api(Function<String, String> fn) {
      System.out.println(fn.apply("OEM-"));
      return (v) -> v + "-OEM";
    }
  }

  static class ProgramClass implements PseudoPlatformInterface {
    public Function<String, String> api(Function<String, String> fn) {
      System.out.println(fn.apply("DEFAULT-"));
      return (v) -> v + "-DEFAULT";
    }

    public static void main(String[] args) {
      PseudoPlatformInterface pseudoPlatformInterface = null;
      try {
        Class<?> oemClass =
            Class.forName(
                "com.android.tools.r8.desugar.desugaredlibrary.PseudoPlatformApiTest$OemClass");
        pseudoPlatformInterface =
            (PseudoPlatformInterface) oemClass.getDeclaredConstructor().newInstance();
      } catch (ClassNotFoundException
          | NoSuchMethodException
          | InstantiationException
          | InvocationTargetException
          | IllegalAccessException e) {
        // Could not load OEM class use built-in program class.
        pseudoPlatformInterface = new ProgramClass();
      }
      Function<String, String> fn = (v) -> v + "X";
      System.out.println(pseudoPlatformInterface.api(fn).apply("Y"));
    }
  }
}
