// 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.getJavaExecutable;
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<>();

  private boolean addR8ExternalDeps = false;

  private ExternalR8TestBuilder(TestState state, Builder builder, Backend backend) {
    super(state, builder, backend);
  }

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

  @Override
  ExternalR8TestBuilder self() {
    return this;
  }

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

      String classPath =
          addR8ExternalDeps
              ? r8jar.toAbsolutePath().toString() + ":" + ToolHelper.DEPS_NOT_RELOCATED
              : r8jar.toAbsolutePath().toString();

      List<String> command = new ArrayList<>();
      Collections.addAll(
          command,
          getJavaExecutable(),
          "-ea",
          "-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());
        }
      }
      command.addAll(programJars.stream().map(Path::toString).collect(Collectors.toList()));

      ProcessBuilder processBuilder = new ProcessBuilder(command);
      ProcessResult processResult = ToolHelper.runProcess(processBuilder);
      assertEquals(processResult.stderr, 0, processResult.exitCode);
      String proguardMap =
          proguardMapFile.toFile().exists()
              ? FileUtils.readTextFile(proguardMapFile, Charsets.UTF_8)
              : "";
      return new ExternalR8TestCompileResult(getState(), outputJar, processResult, proguardMap);
    } catch (IOException e) {
      throw new CompilationFailedException(e);
    }
  }

  @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 addLibraryFiles(Collection<Path> files) {
    libJars.addAll(files);
    return self();
  }

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