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

import static com.android.tools.r8.ToolHelper.CLASSPATH_SEPARATOR;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.base.Charsets;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

// The type arguments R8Command, Builder is not relevant for running external R8.
public class ExternalR8TestBuilder
    extends TestShrinkerBuilder<
        R8Command,
        Builder,
        ExternalR8TestCompileResult,
        ExternalR8TestRunResult,
        ExternalR8TestBuilder> {

  // The r8.jar to run.
  private List<Path> r8Classpath = ToolHelper.getBuildPropR8RuntimePath();

  // Ordered list of program jar entries.
  private final List<Path> programJars = new ArrayList<>();

  // Ordered list of library jar entries.
  private final List<Path> libJars = new ArrayList<>();

  // Proguard configuration file lines.
  private final List<String> config = new ArrayList<>();

  // Additional Proguard configuration files.
  private List<Path> proguardConfigFiles = new ArrayList<>();

  // External JDK to use to run R8
  private final TestRuntime runtime;

  // Enable/disable compiling with assertions
  private boolean enableAssertions = true;

  // Allow test proguard options
  private boolean allowTestProguardOptions = false;

  private String dumpInputToFile = null;
  private String dumpInputToDirectory = null;

  private boolean addR8ExternalDeps = false;

  private List<String> jvmFlags = new ArrayList<>();

  private ExternalR8TestBuilder(
      TestState state, Builder builder, Backend backend, TestRuntime runtime) {
    super(state, builder, backend);
    assert runtime != null;
    this.runtime = runtime;
  }

  public static ExternalR8TestBuilder create(
      TestState state, Backend backend, TestRuntime runtime) {
    return new ExternalR8TestBuilder(state, R8Command.builder(), backend, runtime);
  }

  @Override
  ExternalR8TestBuilder self() {
    return this;
  }

  public List<String> getConfig() {
    return Collections.unmodifiableList(config);
  }

  public ExternalR8TestBuilder addJvmFlag(String flag) {
    jvmFlags.add(flag);
    return self();
  }

  public ExternalR8TestBuilder enableAssertions(boolean enable) {
    enableAssertions = enable;
    return self();
  }

  public ExternalR8TestBuilder allowTestProguardOptions(boolean allow) {
    allowTestProguardOptions = allow;
    return self();
  }

  public ExternalR8TestBuilder dumpInputToFile(String arg) {
    dumpInputToFile = arg;
    return self();
  }

  public ExternalR8TestBuilder dumpInputToDirectory(String arg) {
    dumpInputToDirectory = arg;
    return self();
  }

  @Override
  ExternalR8TestCompileResult internalCompile(
      Builder builder,
      Consumer<InternalOptions> optionsConsumer,
      Supplier<AndroidApp> app,
      BenchmarkResults benchmarkResults)
      throws CompilationFailedException {
    assert benchmarkResults == null;
    assert !libraryDesugaringTestConfiguration.isEnabled();
    try {
      Path outputFolder = getState().getNewTempFolder();
      Path outputJar = outputFolder.resolve("output.jar");
      Path proguardMapFile = outputFolder.resolve("output.jar.map");

      List<Path> classpathList = new ArrayList<>(r8Classpath);
      if (addR8ExternalDeps) {
        classpathList.add(ToolHelper.getDeps());
      }

      String classPath =
          String.join(
              CLASSPATH_SEPARATOR,
              ListUtils.map(classpathList, p -> p.toAbsolutePath().toString()));
      List<String> command = new ArrayList<>();
      if (runtime.isDex()) {
        throw new Unimplemented();
      }
      Collections.addAll(command, runtime.asCf().getJavaExecutable().toString());

      command.addAll(jvmFlags);

      if (enableAssertions) {
        command.add("-ea");
      }

      if (allowTestProguardOptions) {
        command.add("-Dcom.android.tools.r8.allowTestProguardOptions=true");
      }

      Collections.addAll(
          command,
          "-cp",
          classPath,
          R8.class.getTypeName(),
          "--output",
          outputJar.toAbsolutePath().toString(),
          "--pg-map-output",
          proguardMapFile.toString(),
          backend == Backend.CF ? "--classfile" : "--dex",
          builder.getMode() == CompilationMode.DEBUG ? "--debug" : "--release");
      if (!config.isEmpty()) {
        Path proguardConfigFile = outputFolder.resolve("proguard-config.txt");
        FileUtils.writeTextFile(proguardConfigFile, config);
        command.add("--pg-conf");
        command.add(proguardConfigFile.toAbsolutePath().toString());
      }
      for (Path proguardConfigFile : proguardConfigFiles) {
        command.add("--pg-conf");
        command.add(proguardConfigFile.toAbsolutePath().toString());
      }
      if (libJars.isEmpty()) {
        command.add("--lib");
        command.add(TestBase.runtimeJar(backend).toAbsolutePath().toString());
      } else {
        for (Path libJar : libJars) {
          command.add("--lib");
          command.add(libJar.toAbsolutePath().toString());
        }
      }
      if (dumpInputToFile != null) {
        command.add("--dumpinputtofile");
        command.add(dumpInputToFile);
      }
      if (dumpInputToDirectory != null) {
        command.add("--dumpinputtodirectory");
        command.add(dumpInputToDirectory);
      }
      command.addAll(programJars.stream().map(Path::toString).collect(Collectors.toList()));

      ProcessBuilder processBuilder = new ProcessBuilder(command);
      ProcessResult processResult = ToolHelper.runProcess(processBuilder, getStdoutForTesting());
      assertEquals(
          "STDOUT\n:" + processResult.stdout + "\nSTDERR:\n" + processResult.stderr,
          0,
          processResult.exitCode);
      String proguardMap =
          proguardMapFile.toFile().exists()
              ? FileUtils.readTextFile(proguardMapFile, Charsets.UTF_8)
              : "";
      return new ExternalR8TestCompileResult(
          getState(), outputJar, processResult, proguardMap, getMinApiLevel(), getOutputMode());
    } catch (IOException e) {
      throw InternalCompilationFailedExceptionUtils.createForTesting(e);
    }
  }

  @Override
  public ExternalR8TestBuilder addApplyMapping(String proguardMap) {
    throw new Unimplemented("No support for adding mapfile content yet");
  }

  @Override
  public ExternalR8TestBuilder addDataEntryResources(DataEntryResource... resources) {
    throw new Unimplemented("No support for adding data entry resources");
  }

  @Override
  public ExternalR8TestBuilder addProgramClasses(Collection<Class<?>> classes) {
    // Adding a collection of classes will build a jar of exactly those classes so that no other
    // classes are made available via a too broad classpath directory.
    try {
      Path programJar = getState().getNewTempFolder().resolve("input.jar");
      ClassFileConsumer inputConsumer = new ClassFileConsumer.ArchiveConsumer(programJar);
      for (Class<?> clazz : classes) {
        String descriptor = DescriptorUtils.javaTypeToDescriptor(clazz.getName());
        inputConsumer.accept(ByteDataView.of(ToolHelper.getClassAsBytes(clazz)), descriptor, null);
      }
      inputConsumer.finished(null);
      programJars.add(programJar);
      return self();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public ExternalR8TestBuilder addProgramFiles(Collection<Path> files) {
    for (Path file : files) {
      if (FileUtils.isJarFile(file)) {
        programJars.add(file);
      } else {
        throw new Unimplemented("No support for adding paths directly");
      }
    }
    return self();
  }

  @Override
  public ExternalR8TestBuilder addProgramClassFileData(Collection<byte[]> classes) {
    try {
      Path out = getState().getNewTempFolder().resolve("out.jar");
      TestBase.writeClassFileDataToJar(out, classes);
      programJars.add(out);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return self();
  }

  @Override
  public ExternalR8TestBuilder addProgramDexFileData(Collection<byte[]> data) {
    throw new Unimplemented("No support for adding dex file data directly");
  }

  @Override
  public ExternalR8TestBuilder addLibraryFiles(Collection<Path> files) {
    libJars.addAll(files);
    return self();
  }

  @Override
  public ExternalR8TestBuilder addClasspathClasses(Collection<Class<?>> classes) {
    throw new Unimplemented("No support for adding classpath data directly");
  }

  @Override
  public ExternalR8TestBuilder addClasspathFiles(Collection<Path> files) {
    throw new Unimplemented("No support for adding classpath data directly");
  }

  @Override
  public ExternalR8TestBuilder addKeepRuleFiles(List<Path> proguardConfigFiles) {
    this.proguardConfigFiles.addAll(proguardConfigFiles);
    return self();
  }

  @Override
  public ExternalR8TestBuilder addKeepRules(Collection<String> rules) {
    config.addAll(rules);
    return self();
  }

  public ExternalR8TestBuilder useR8WithRelocatedDeps() {
    return useProvidedR8(ToolHelper.getR8WithRelocatedDeps());
  }

  public ExternalR8TestBuilder useProvidedR8(Path r8jar) {
    this.r8Classpath = Collections.singletonList(r8jar);
    return self();
  }

  public ExternalR8TestBuilder addR8ExternalDepsToClasspath() {
    this.addR8ExternalDeps = true;
    return self();
  }
}
