// Copyright (c) 2021, 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 junit.framework.Assert.assertNull;
import static junit.framework.TestCase.assertTrue;

import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidAppConsumers;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
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.concurrent.ExecutionException;
import java.util.function.Consumer;

public class L8TestBuilder {

  private final AndroidApiLevel apiLevel;
  private final Backend backend;
  private final TestState state;

  private CompilationMode mode = CompilationMode.RELEASE;
  private String generatedKeepRules = null;
  private List<String> keepRules = new ArrayList<>();
  private List<Path> additionalProgramFiles = new ArrayList<>();
  private List<byte[]> additionalProgramClassFileData = new ArrayList<>();
  private Consumer<InternalOptions> optionsModifier = ConsumerUtils.emptyConsumer();
  private Path desugarJDKLibs = ToolHelper.getDesugarJDKLibs();
  private Path desugarJDKLibsConfiguration = null;
  private StringResource desugaredLibrarySpecification =
      StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting());
  private List<Path> libraryFiles = new ArrayList<>();

  private L8TestBuilder(AndroidApiLevel apiLevel, Backend backend, TestState state) {
    this.apiLevel = apiLevel;
    this.backend = backend;
    this.state = state;
  }

  public static L8TestBuilder create(AndroidApiLevel apiLevel, Backend backend, TestState state) {
    return new L8TestBuilder(apiLevel, backend, state);
  }

  public L8TestBuilder addProgramFiles(Collection<Path> programFiles) {
    this.additionalProgramFiles.addAll(programFiles);
    return this;
  }

  public L8TestBuilder addProgramClassFileData(byte[]... classes) {
    this.additionalProgramClassFileData.addAll(Arrays.asList(classes));
    return this;
  }

  public L8TestBuilder addLibraryFiles(Path... libraryFiles) {
    Collections.addAll(this.libraryFiles, libraryFiles);
    return this;
  }

  public L8TestBuilder addGeneratedKeepRules(String generatedKeepRules) {
    assertNull(this.generatedKeepRules);
    this.generatedKeepRules = generatedKeepRules;
    return this;
  }

  public L8TestBuilder addKeepRuleFile(Path keepRuleFile) throws IOException {
    this.keepRules.add(FileUtils.readTextFile(keepRuleFile, StandardCharsets.UTF_8));
    return this;
  }

  public L8TestBuilder addKeepRuleFiles(Collection<Path> keepRuleFiles) throws IOException {
    for (Path keepRuleFile : keepRuleFiles) {
      addKeepRuleFile(keepRuleFile);
    }
    return this;
  }

  public L8TestBuilder addOptionsModifier(Consumer<InternalOptions> optionsModifier) {
    this.optionsModifier = this.optionsModifier.andThen(optionsModifier);
    return this;
  }

  public L8TestBuilder applyIf(boolean condition, ThrowableConsumer<L8TestBuilder> thenConsumer) {
    return applyIf(condition, thenConsumer, ThrowableConsumer.empty());
  }

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

  public TestDiagnosticMessages getDiagnosticMessages() {
    return state.getDiagnosticsMessages();
  }

  public L8TestBuilder setDebug() {
    this.mode = CompilationMode.DEBUG;
    return this;
  }

  public L8TestBuilder setDesugarJDKLibs(Path desugarJDKLibs) {
    assert desugarJDKLibs != null : "Use noDefaultDesugarJDKLibs to clear the default.";
    this.desugarJDKLibs = desugarJDKLibs;
    return this;
  }

  public L8TestBuilder noDefaultDesugarJDKLibs() {
    this.desugarJDKLibs = null;
    return this;
  }

  public L8TestBuilder setDesugarJDKLibsConfiguration(Path desugarJDKLibsConfiguration) {
    this.desugarJDKLibsConfiguration = desugarJDKLibsConfiguration;
    return this;
  }

  public L8TestBuilder setDesugaredLibraryConfiguration(Path path) {
    this.desugaredLibrarySpecification = StringResource.fromFile(path);
    return this;
  }

  public L8TestBuilder setDesugaredLibraryConfiguration(StringResource configuration) {
    this.desugaredLibrarySpecification = configuration;
    return this;
  }

  public L8TestBuilder setDisableL8AnnotationRemoval(boolean disableL8AnnotationRemoval) {
    return addOptionsModifier(
        options -> options.disableL8AnnotationRemoval = disableL8AnnotationRemoval);
  }

  public L8TestCompileResult compile()
      throws IOException, CompilationFailedException, ExecutionException {
    // We wrap exceptions in a RuntimeException to call this from a lambda.
    AndroidAppConsumers sink = new AndroidAppConsumers();
    L8Command.Builder l8Builder =
        L8Command.builder(state.getDiagnosticsHandler())
            .addProgramFiles(getProgramFiles())
            .addLibraryFiles(getLibraryFiles())
            .setMode(mode)
            .addDesugaredLibraryConfiguration(desugaredLibrarySpecification)
            .setMinApiLevel(apiLevel.getLevel())
            .setProgramConsumer(
                backend.isCf()
                    ? sink.wrapProgramConsumer(ClassFileConsumer.emptyConsumer())
                    : sink.wrapProgramConsumer(DexIndexedConsumer.emptyConsumer()));
    addProgramClassFileData(l8Builder);
    Path mapping = null;
    if (!keepRules.isEmpty() || generatedKeepRules != null) {
      mapping = state.getNewTempFile("mapping.txt");
      l8Builder
          .addProguardConfiguration(
              ImmutableList.<String>builder()
                  .addAll(keepRules)
                  .addAll(
                      generatedKeepRules != null
                          ? ImmutableList.of(generatedKeepRules)
                          : Collections.emptyList())
                  .build(),
              Origin.unknown())
          .setProguardMapOutputPath(mapping);
    }
    ToolHelper.runL8(l8Builder.build(), optionsModifier);
    return new L8TestCompileResult(sink.build(), apiLevel, generatedKeepRules, mapping, state)
        .inspect(
            inspector ->
                inspector.forAllClasses(
                    clazz ->
                        assertTrue(
                            clazz.getFinalName().startsWith("j$.")
                                || clazz.getFinalName().startsWith("java."))));
  }

  private Collection<Path> getProgramFiles() {
    ImmutableList.Builder<Path> builder = ImmutableList.builder();
    if (desugarJDKLibs != null) {
      builder.add(desugarJDKLibs);
    }
    if (desugarJDKLibsConfiguration != null) {
      builder.add(desugarJDKLibsConfiguration);
    }
    return builder.addAll(additionalProgramFiles).build();
  }

  private L8Command.Builder addProgramClassFileData(L8Command.Builder builder) {
    additionalProgramClassFileData.forEach(
        data -> builder.addClassProgramData(data, Origin.unknown()));
    return builder;
  }

  private Collection<Path> getLibraryFiles() {
    return libraryFiles;
  }
}
