// 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.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.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 Path r8jar = ToolHelper.R8_JAR;

  // 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 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)
      throws CompilationFailedException {
    assert !libraryDesugaringTestConfiguration.isEnabled();
    try {
      Path outputFolder = getState().getNewTempFolder();
      Path outputJar = outputFolder.resolve("output.jar");
      Path proguardMapFile = outputFolder.resolve("output.jar.map");

      String classPath =
          addR8ExternalDeps
              ? r8jar.toAbsolutePath().toString() + CLASSPATH_SEPARATOR + ToolHelper.DEPS
              : r8jar.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 new CompilationFailedException(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) {
    throw new Unimplemented("No support for adding classfile data directly");
  }

  @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.R8_WITH_RELOCATED_DEPS_JAR);
  }

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

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