// Copyright (c) 2019, 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.ir.desugar.backports;

import static org.junit.Assert.assertEquals;

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;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.cf.CfCodePrinter;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.JarApplicationReader;
import com.android.tools.r8.graph.JarClassFileReader;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

// Class to generate and validate CfCode for backport methods.
@RunWith(Parameterized.class)
public class GenerateBackportMethods extends TestBase {

  static final Path googleFormatDir = Paths.get(ToolHelper.THIRD_PARTY_DIR, "google-java-format");
  static final Path googleFormatJar =
      googleFormatDir.resolve("google-java-format-1.7-all-deps.jar");
  static final Path backportMethodsFile =
      Paths.get(
          ToolHelper.SOURCE_DIR,
          "com",
          "android",
          "tools",
          "r8",
          "ir",
          "desugar",
          "backports",
          "BackportedMethods.java");

  static final String header =
      StringUtils.lines(
          "// Copyright (c) 2019, 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.",
          "",
          "// ***********************************************************************************",
          "// GENERATED FILE. DO NOT EDIT! Changes should be made to GenerateBackportMethods.java",
          "// ***********************************************************************************",
          "",
          "package com.android.tools.r8.ir.desugar.backports;");

  static final List<Class<?>> methodTemplateClasses =
      ImmutableList.of(
          BooleanMethods.class,
          ByteMethods.class,
          CharSequenceMethods.class,
          CharacterMethods.class,
          CloseResourceMethod.class,
          CollectionMethods.class,
          CollectionsMethods.class,
          DoubleMethods.class,
          FloatMethods.class,
          IntegerMethods.class,
          LongMethods.class,
          MathMethods.class,
          ObjectsMethods.class,
          OptionalMethods.class,
          ShortMethods.class,
          StreamMethods.class,
          StringMethods.class);

  final TestParameters parameters;

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

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

  @Test
  public void test() throws Exception {
    ArrayList<Class<?>> sorted = new ArrayList<>(methodTemplateClasses);
    sorted.sort(Comparator.comparing(Class::getTypeName));
    assertEquals("Classes should be listed in sorted order", sorted, methodTemplateClasses);
    assertEquals(
        FileUtils.readTextFile(backportMethodsFile, StandardCharsets.UTF_8),
        generateBackportMethods(parameters.getRuntime().asCf().getJavaExecutable().toString()));
  }

  // Running this method will regenerate / overwrite the content of the backport methods.
  public static void main(String[] args) throws Exception {
    FileUtils.writeToFile(
        backportMethodsFile,
        null,
        generateBackportMethods(ToolHelper.getSystemJavaExecutable()).getBytes());
  }

  private static String generateBackportMethods(String javaExecutable) throws IOException {
    InternalOptions options = new InternalOptions();
    CfCodePrinter codePrinter = new CfCodePrinter();
    JarClassFileReader reader =
        new JarClassFileReader(
            new JarApplicationReader(options),
            clazz -> {
              for (DexEncodedMethod method : clazz.allMethodsSorted()) {
                if (method.isInitializer()) {
                  continue;
                }
                String methodName =
                    method.method.holder.getName() + "_" + method.method.name.toString();
                codePrinter.visitMethod(methodName, method.getCode().asCfCode());
              }
            });
    for (Class<?> clazz : methodTemplateClasses) {
      try (InputStream stream = Files.newInputStream(ToolHelper.getClassFileForTestClass(clazz))) {
        reader.read(Origin.unknown(), ClassKind.PROGRAM, stream);
      }
    }

    Path outfile = Paths.get(ToolHelper.BUILD_DIR, "backports.java");
    try (PrintStream printer = new PrintStream(Files.newOutputStream(outfile))) {
      printer.println(header);
      codePrinter.getImports().forEach(i -> printer.println("import " + i + ";"));
      printer.println("public final class BackportedMethods {\n");
      codePrinter.getMethods().forEach(printer::println);
      printer.println("}");
    }

    ProcessBuilder builder =
        new ProcessBuilder(
            ImmutableList.of(
                javaExecutable,
                "-jar",
                googleFormatJar.toString(),
                outfile.toAbsolutePath().toString()));
    String commandString = String.join(" ", builder.command());
    System.out.println(commandString);
    Process process = builder.start();
    ProcessResult result = ToolHelper.drainProcessOutputStreams(process, commandString);
    if (result.exitCode != 0) {
      throw new IllegalStateException(result.toString());
    }
    String content = result.stdout;
    if (!StringUtils.LINE_SEPARATOR.equals("\n")) {
      return content.replace(StringUtils.LINE_SEPARATOR, "\n");
    }
    return content;
  }
}
