// Copyright (c) 2018, 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.DiagnosticsMatcher.diagnosticMessage;
import static com.android.tools.r8.TestBase.Backend.DEX;
import static com.android.tools.r8.TestBase.testForD8;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.TestRuntime.DexRuntime;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.debug.DebugTestConfig;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Box;
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.ThrowingConsumer;
import com.android.tools.r8.utils.TriFunction;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ObjectArrays;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.hamcrest.Matcher;

public abstract class TestCompileResult<
        CR extends TestCompileResult<CR, RR>, RR extends TestRunResult<RR>>
    extends TestBaseResult<CR, RR> {

  public final AndroidApp app;
  public final int minApiLevel;
  private final OutputMode outputMode;
  final List<Path> additionalRunClassPath = new ArrayList<>();
  final List<Path> additionalBootClasspath = new ArrayList<>();
  final List<String> vmArguments = new ArrayList<>();
  private boolean withArt6Plus64BitsLib = false;
  private boolean withArtFrameworks = true;
  private LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration;

  TestCompileResult(TestState state, AndroidApp app, int minApiLevel, OutputMode outputMode) {
    super(state);
    this.app = app;
    this.minApiLevel = minApiLevel;
    this.outputMode = outputMode;
    this.libraryDesugaringTestConfiguration = LibraryDesugaringTestConfiguration.DISABLED;
  }

  TestCompileResult(
      TestState state,
      AndroidApp app,
      int minApiLevel,
      OutputMode outputMode,
      LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration) {
    super(state);
    this.app = app;
    this.minApiLevel = minApiLevel;
    this.outputMode = outputMode;
    this.libraryDesugaringTestConfiguration = libraryDesugaringTestConfiguration;
  }

  public CR applyIf(boolean condition, ThrowableConsumer<CR> thenConsumer) {
    return applyIf(condition, thenConsumer, result -> {});
  }

  public CR applyIf(
      boolean condition, ThrowableConsumer<CR> thenConsumer, ThrowableConsumer<CR> elseConsumer) {
    if (condition) {
      thenConsumer.acceptWithRuntimeException(self());
    } else {
      elseConsumer.acceptWithRuntimeException(self());
    }
    return self();
  }

  public final CR withArt6Plus64BitsLib() {
    withArt6Plus64BitsLib = true;
    return self();
  }

  public final CR withArtFrameworks() {
    withArtFrameworks = true;
    return self();
  }

  public final AndroidApp getApp() {
    return app;
  }

  public final Backend getBackend() {
    if (outputMode == OutputMode.ClassFile) {
      return Backend.CF;
    }
    assert outputMode == OutputMode.DexIndexed
        || outputMode == OutputMode.DexFilePerClass
        || outputMode == OutputMode.DexFilePerClassFile;
    return Backend.DEX;
  }

  public abstract TestDiagnosticMessages getDiagnosticMessages();

  public CR inspectDiagnosticMessages(Consumer<TestDiagnosticMessages> consumer) {
    consumer.accept(getDiagnosticMessages());
    return self();
  }

  public abstract Set<String> getMainDexClasses();

  public final CR inspectMainDexClasses(Consumer<Set<String>> consumer) {
    consumer.accept(getMainDexClasses());
    return self();
  }

  public final CR inspectMainDexClasses(BiConsumer<CodeInspector, Set<String>> consumer)
      throws IOException {
    consumer.accept(inspector(), getMainDexClasses());
    return self();
  }

  public abstract String getStdout();

  public abstract String getStderr();

  public OutputMode getOutputMode() {
    return outputMode;
  }

  protected abstract RR createRunResult(TestRuntime runtime, ProcessResult result);

  @Deprecated
  public RR run(Class<?> mainClass) throws ExecutionException, IOException {
    return run(mainClass.getTypeName());
  }

  @Deprecated
  public RR run(String mainClass) throws ExecutionException, IOException {
    assert !libraryDesugaringTestConfiguration.isEnabled();
    ClassSubject mainClassSubject = inspector().clazz(mainClass);
    assertThat(mainClassSubject, isPresent());
    switch (getBackend()) {
      case DEX:
        return runArt(
            new DexRuntime(ToolHelper.getDexVm()),
            mainClassSubject.getFinalName());
      case CF:
        return runJava(
            TestRuntime.getDefaultJavaRuntime(),
            mainClassSubject.getFinalName());
      default:
        throw new Unreachable();
    }
  }

  public RR run(TestRuntime runtime, Class<?> mainClass) throws ExecutionException, IOException {
    return run(runtime, mainClass.getTypeName());
  }

  public RR run(TestRuntime runtime, Class<?> mainClass, String... args)
      throws ExecutionException, IOException {
    return run(runtime, mainClass.getTypeName(), args);
  }

  public RR run(TestRuntime runtime, String mainClass) throws ExecutionException, IOException {
    return run(runtime, mainClass, new String[] {});
  }

  public RR run(TestRuntime runtime, String mainClass, String... args)
      throws ExecutionException, IOException {
    assert getBackend() == runtime.getBackend();
    ClassSubject mainClassSubject = inspector().clazz(mainClass);
    if (!mainClassSubject.isPresent()) {
      for (Path classpathFile : additionalRunClassPath) {
        mainClassSubject = new CodeInspector(classpathFile).clazz(mainClass);
        if (mainClassSubject.isPresent()) {
          break;
        }
      }
    }
    assertThat("Did you forget a keep rule for the main method?", mainClassSubject, isPresent());
    if (runtime.isDex()) {
      return runArt(runtime, mainClassSubject.getFinalName(), args);
    }
    assert runtime.isCf();
    return runJava(
        runtime,
        ObjectArrays.concat(mainClassSubject.getFinalName(), args));
  }

  public RR runWithJaCoCo(Path output, TestRuntime runtime, String mainClass, String... args)
      throws IOException, ExecutionException {
    setSystemProperty("jacoco-agent.destfile", output.toString());
    setSystemProperty("jacoco-agent.dumponexit", "true");
    setSystemProperty("jacoco-agent.output", "file");
    return run(runtime, mainClass, args);
  }

  public CR addRunClasspathFiles(Path... classpath) {
    return addRunClasspathFiles(Arrays.asList(classpath));
  }

  public CR addRunClasspathFiles(List<Path> classpath) {
    additionalRunClassPath.addAll(classpath);
    return self();
  }

  public CR addRunClasspathClasses(Class<?>... classpath) throws Exception {
    return addRunClasspathClasses(Arrays.asList(classpath));
  }

  public CR addRunClasspathClasses(List<Class<?>> classpath) throws Exception {
    if (getBackend() == Backend.DEX) {
      return addRunClasspathFiles(
          testForD8(state.getTempFolder())
              .addProgramClasses(classpath)
              .setMinApi(minApiLevel)
              .compile()
              .writeToZip());
    }
    assert getBackend() == Backend.CF;
    try {
      Path path = state.getNewTempFolder().resolve("runtime-classes.jar");
      ArchiveConsumer consumer = new ArchiveConsumer(path);
      for (Class clazz : classpath) {
        consumer.accept(
            ByteDataView.of(ToolHelper.getClassAsBytes(clazz)),
            DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName()),
            null);
      }
      consumer.finished(null);
      additionalRunClassPath.addAll(Collections.singletonList(path));
      return self();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public CR addRunClasspathClassFileData(byte[]... classes) throws Exception {
    return addRunClasspathClassFileData(Arrays.asList(classes));
  }

  public CR addRunClasspathClassFileData(Collection<byte[]> classes) throws Exception {
    if (getBackend() == Backend.DEX) {
      additionalRunClassPath.add(
          testForD8(state.getTempFolder())
              .addProgramClassFileData(classes)
              .setMinApi(minApiLevel)
              .compile()
              .writeToZip());
      return self();
    }
    assert getBackend() == Backend.CF;
    try {
      AndroidApp.Builder appBuilder = AndroidApp.builder();
      for (byte[] clazz : classes) {
        appBuilder.addClassProgramData(
            clazz, Origin.unknown(), ImmutableSet.of(TestBase.extractClassDescriptor(clazz)));
      }
      Path path = state.getNewTempFolder().resolve("runtime-classes.jar");
      appBuilder.build().writeToZip(path, OutputMode.ClassFile);
      additionalRunClassPath.add(path);
      return self();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public CR addBootClasspathClasses(Class<?>... classes) throws Exception {
    return addBootClasspathClasses(Arrays.asList(classes));
  }

  public CR addBootClasspathClasses(List<Class<?>> classes) throws Exception {
    if (getBackend() == Backend.DEX) {
      additionalBootClasspath.add(
          testForD8(state.getTempFolder())
              .addProgramClasses(classes)
              .setMinApi(minApiLevel)
              .compile()
              .writeToZip());
      return self();
    }
    assert getBackend() == Backend.CF;
    try {
      Path path = state.getNewTempFolder().resolve("runtime-classes.jar");
      ArchiveConsumer consumer = new ArchiveConsumer(path);
      for (Class<?> clazz : classes) {
        consumer.accept(
            ByteDataView.of(ToolHelper.getClassAsBytes(clazz)),
            DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName()),
            null);
      }
      consumer.finished(null);
      additionalBootClasspath.add(path);
      return self();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public CR addBootClasspathFiles(Path... files) {
    return addBootClasspathFiles(Arrays.asList(files));
  }

  public CR addBootClasspathFiles(Collection<Path> files) {
    additionalBootClasspath.addAll(files);
    return self();
  }

  public CR addDesugaredCoreLibraryRunClassPath(
      Function<AndroidApiLevel, Path> classPathSupplier, AndroidApiLevel minAPILevel) {
    addRunClasspathFiles(classPathSupplier.apply(minAPILevel));
    return self();
  }

  public CR addDesugaredCoreLibraryRunClassPath(
      TriFunction<AndroidApiLevel, String, Boolean, Path> classPathSupplier,
      AndroidApiLevel minAPILevel,
      String keepRules,
      boolean shrink) {
    addRunClasspathFiles(classPathSupplier.apply(minAPILevel, keepRules, shrink));
    return self();
  }

  public CR enableRuntimeAssertions() {
    assert getBackend() == Backend.CF;
    if (!vmArguments.contains("-ea")) {
      vmArguments.add("-ea");
    }
    return self();
  }

  public CR enableJVMPreview() {
    assert getBackend() == Backend.CF;
    if (!vmArguments.contains("--enable-preview")) {
      vmArguments.add("--enable-preview");
    }
    return self();
  }

  public CR enableRuntimeAssertions(boolean enable) {
    if (getBackend() == Backend.CF) {
      if (enable) {
        enableRuntimeAssertions();
      }
    } else {
      // Assertions cannot be enabled on dex VMs.
      assert !enable;
    }

    if (enable) {
      if (!this.vmArguments.contains("-ea")) {
        this.vmArguments.add("-ea");
      }
    }
    return self();
  }

  public CR setSystemProperty(String name, String value) {
    vmArguments.add("-D" + name + "=" + value);
    return self();
  }

  public CR writeSingleDexOutputToFile(Path file) throws IOException {
    assertTrue(getApp().getClassProgramResourcesForTesting().isEmpty());
    try {
      List<ProgramResource> dexProgramSources = getApp().getDexProgramResourcesForTesting();
      assertEquals(1, dexProgramSources.size());
      FileUtils.writeToFile(file, null, dexProgramSources.get(0).getBytes());
      return self();
    } catch (ResourceException e) {
      throw new IOException(e);
    }
  }

  public Path writeToZip() throws IOException {
    Path file = state.getNewTempFolder().resolve("out.zip");
    writeToZip(file);
    return file;
  }

  public CR writeToZip(Consumer<Path> fn) throws IOException {
    fn.accept(writeToZip());
    return self();
  }

  public CR writeToZip(Path file) throws IOException {
    app.writeToZip(file, getOutputMode());
    return self();
  }

  public Path writeToDirectory() throws IOException {
    Path directory = state.getNewTempFolder();
    writeToDirectory(directory);
    return directory;
  }

  public CR writeToDirectory(Path directory) throws IOException {
    app.writeToDirectory(directory, getOutputMode());
    return self();
  }

  public CodeInspector inspector() throws IOException {
    return new CodeInspector(app);
  }

  public CodeInspector inspector(Consumer<InternalOptions> debugOptionsConsumer)
      throws IOException {
    return new CodeInspector(app, debugOptionsConsumer);
  }

  public <E extends Throwable> CR inspect(ThrowingConsumer<CodeInspector, E> consumer)
      throws IOException, E {
    consumer.accept(inspector());
    return self();
  }

  @SuppressWarnings("unchecked")
  public <E extends Throwable> CR inspectMultiDex(ThrowingConsumer<CodeInspector, E>... consumers)
      throws IOException, E {
    return inspectMultiDex(null, consumers);
  }

  @SafeVarargs
  public final <E extends Throwable> CR inspectMultiDex(
      Path mappingFile, ThrowingConsumer<CodeInspector, E>... consumers) throws IOException, E {
    Path out = state.getNewTempFolder();
    getApp().writeToDirectory(out, OutputMode.DexIndexed);
    consumers[0].accept(new CodeInspector(out.resolve("classes.dex"), mappingFile));
    for (int i = 1; i < consumers.length; i++) {
      Path dex = out.resolve("classes" + (i + 1) + ".dex");
      CodeInspector inspector =
          dex.toFile().exists() ? new CodeInspector(dex, mappingFile) : CodeInspector.empty();
      consumers[i].accept(inspector);
    }
    return self();
  }

  public <E extends Throwable> CR inspectWithOptions(
      ThrowingConsumer<CodeInspector, E> consumer, Consumer<InternalOptions> debugOptionsConsumer)
      throws IOException, E {
    consumer.accept(inspector(debugOptionsConsumer));
    return self();
  }

  public CR assertNoMessages() {
    getDiagnosticMessages().assertNoMessages();
    return self();
  }

  public CR assertOnlyInfos() {
    getDiagnosticMessages().assertOnlyInfos();
    return self();
  }

  public CR assertOnlyWarnings() {
    getDiagnosticMessages().assertOnlyWarnings();
    return self();
  }

  public CR assertOnlyErrors() {
    getDiagnosticMessages().assertOnlyErrors();
    return self();
  }

  public CR assertDiagnosticThatMatches(Matcher<Diagnostic> matcher) {
    getDiagnosticMessages().assertDiagnosticThatMatches(matcher);
    return self();
  }

  public CR assertInfoThatMatches(Matcher<Diagnostic> matcher) {
    getDiagnosticMessages().assertInfoThatMatches(matcher);
    return self();
  }

  public CR assertInfoMessageThatMatches(Matcher<String> matcher) {
    getDiagnosticMessages().assertInfoThatMatches(diagnosticMessage(matcher));
    return self();
  }

  public CR assertAllInfosMatch(Matcher<Diagnostic> matcher) {
    getDiagnosticMessages().assertNoInfosMatch(not(matcher));
    return self();
  }

  public CR assertAllInfoMessagesMatch(Matcher<String> matcher) {
    return assertNoInfoMessageThatMatches(not(matcher));
  }

  public CR assertNoInfoThatMatches(Matcher<Diagnostic> matcher) {
    getDiagnosticMessages().assertNoInfosMatch(matcher);
    return self();
  }

  public CR assertNoInfoMessageThatMatches(Matcher<String> matcher) {
    getDiagnosticMessages().assertNoInfosMatch(diagnosticMessage(matcher));
    return self();
  }

  public CR assertAtLeastOneInfoMessage() {
    assertTrue(getDiagnosticMessages().getInfos().size() >= 1);
    return self();
  }

  public CR assertInfosCount(int count) {
    getDiagnosticMessages().assertInfosCount(count);
    return self();
  }

  public CR assertNoInfoMessages() {
    getDiagnosticMessages().assertNoInfos();
    return self();
  }

  public CR assertWarningMessageThatMatches(Matcher<String> matcher) {
    getDiagnosticMessages().assertWarningMessageThatMatches(matcher);
    return self();
  }

  public CR assertWarningThatMatches(Matcher<Diagnostic> matcher) {
    getDiagnosticMessages().assertWarningThatMatches(matcher);
    return self();
  }

  public CR assertAllWarningMessagesMatch(Matcher<String> matcher) {
    getDiagnosticMessages().assertHasWarnings().assertAllWarningsMatch(diagnosticMessage(matcher));
    return self();
  }

  public CR assertNoWarningMessages() {
    getDiagnosticMessages().assertNoWarnings();
    return self();
  }

  public CR assertNoWarningMessageThatMatches(Matcher<String> matcher) {
    getDiagnosticMessages().assertNoWarningsMatch(diagnosticMessage(matcher));
    return self();
  }

  public CR assertErrorMessageThatMatches(Matcher<String> matcher) {
    getDiagnosticMessages().assertErrorMessageThatMatches(matcher);
    return self();
  }

  public CR assertNoErrorMessages() {
    getDiagnosticMessages().assertNoErrors();
    return self();
  }

  public CR assertNoStdout() {
    assertEquals("", getStdout());
    return self();
  }

  public CR assertStdoutThatMatches(Matcher<String> matcher) {
    assertThat(getStdout(), matcher);
    return self();
  }

  public CR assertNoStderr() {
    assertEquals("", getStderr());
    return self();
  }

  public CR assertStderrThatMatches(Matcher<String> matcher) {
    assertThat(getStderr(), matcher);
    return self();
  }

  public CR disassemble(PrintStream ps) throws IOException, ExecutionException {
    ToolHelper.disassemble(app, ps);
    return self();
  }

  public CR disassemble() throws IOException, ExecutionException {
    return disassemble(System.out);
  }

  @Deprecated
  public DebugTestConfig debugConfig() {
    return debugConfig(
        getBackend().isCf()
            ? TestRuntime.getDefaultCfRuntime()
            : new DexRuntime(ToolHelper.getDexVm()));
  }

  public DebugTestConfig debugConfig(TestRuntime runtime) {
    assert runtime.getBackend() == getBackend();
    // Rethrow exceptions since debug config is usually used in a delayed wrapper which
    // does not declare exceptions.
    try {
      Path out = state.getNewTempFolder().resolve("out.zip");
      app.writeToZip(out, getOutputMode());
      return DebugTestConfig.create(runtime, out);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private RR runJava(TestRuntime runtime, String... arguments) throws IOException {
    assert runtime != null;
    Path out = state.getNewTempFolder().resolve("out.zip");
    app.writeToZip(out, OutputMode.ClassFile);
    List<Path> classPath =
        ImmutableList.<Path>builder().addAll(additionalRunClassPath).add(out).build();
    ProcessResult result =
        ToolHelper.runJava(
            runtime.asCf(), vmArguments, additionalBootClasspath, classPath, arguments);
    return createRunResult(runtime, result);
  }

  RR runArt(TestRuntime runtime, String mainClass, String... arguments) throws IOException {
    DexVm vm = runtime.asDex().getVm();
    // TODO(b/127785410): Always assume a non-null runtime.
    Path out = state.getNewTempFolder().resolve("out.zip");
    app.writeToZip(out, OutputMode.DexIndexed);
    List<String> classPath =
        ImmutableList.<String>builder()
            .addAll(
                additionalRunClassPath.stream().map(Path::toString).collect(Collectors.toList()))
            .add(out.toString())
            .build();
    Consumer<ArtCommandBuilder> commandConsumer =
        withArt6Plus64BitsLib && vm.getVersion().isNewerThanOrEqual(DexVm.Version.V6_0_1)
            ? builder -> builder.appendArtOption("--64")
            : builder -> {};
    commandConsumer =
        commandConsumer.andThen(
            builder -> {
              if (!additionalBootClasspath.isEmpty()) {
                DexVm dexVm = runtime.asDex().getVm();
                if (dexVm.isNewerThan(DexVm.ART_4_4_4_HOST)) {
                  builder.appendArtOption("-Ximage:/system/non/existent/image.art");
                  builder.appendArtOption("-Xnoimage-dex2oat");
                }
                try {
                  for (String s : ToolHelper.getBootLibs(dexVm)) {
                    builder.appendBootClasspath(new File(s).getCanonicalPath());
                  }
                } catch (Exception e) {
                  throw new RuntimeException();
                }
                additionalBootClasspath.forEach(
                    path -> builder.appendBootClasspath(path.toString()));
              }
              for (String vmArgument : vmArguments) {
                builder.appendArtOption(vmArgument);
              }
            });
    ProcessResult result =
        ToolHelper.runArtRaw(
            classPath, mainClass, commandConsumer, vm, withArtFrameworks, arguments);
    return createRunResult(runtime, result);
  }

  public Dex2OatTestRunResult runDex2Oat(TestRuntime runtime) throws IOException {
    assert getBackend() == DEX;
    DexVm vm = runtime.asDex().getVm();
    Path tmp = state.getNewTempFolder();
    Path jarFile = tmp.resolve("out.jar");
    Path oatFile = tmp.resolve("out.oat");
    app.writeToZip(jarFile, OutputMode.DexIndexed);
    return new Dex2OatTestRunResult(
        app, runtime, ToolHelper.runDex2OatRaw(jarFile, oatFile, vm), state);
  }

  public CR benchmarkCodeSize(BenchmarkResults results) throws IOException {
    Path out = writeToZip();
    Box<Long> size = new Box<>(0L);
    ZipUtils.iter(
        out,
        (entry, stream) -> {
          if ((getBackend().isDex() && entry.getName().endsWith(".dex"))
              || getBackend().isCf() && entry.getName().endsWith(".class")) {
            size.set(size.get() + entry.getSize());
          }
        });
    results.addCodeSizeResult(size.get());
    return self();
  }
}
