// 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 static org.junit.Assert.fail;

import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.errors.UnusedProguardKeepRuleDiagnostic;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.profile.art.ArtProfileConsumer;
import com.android.tools.r8.profile.art.ArtProfileProvider;
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.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class L8TestBuilder {

  private final AndroidApiLevel apiLevel;
  private final Backend backend;
  private final L8Command.Builder l8Builder;
  private final TestState state;

  private CompilationMode mode = CompilationMode.RELEASE;
  private String generatedKeepRules = null;
  private List<String> keepRules = new ArrayList<>();
  private List<Path> programFiles = new ArrayList<>();
  private List<byte[]> programClassFileData = new ArrayList<>();
  private Consumer<InternalOptions> optionsModifier = ConsumerUtils.emptyConsumer();
  private StringResource desugaredLibrarySpecification = null;
  private List<Path> libraryFiles = new ArrayList<>();
  private ProgramConsumer programConsumer;
  private boolean finalPrefixVerification = true;

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

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

  public L8TestBuilder ignoreFinalPrefixVerification() {
    finalPrefixVerification = false;
    return this;
  }

  public L8TestBuilder addProgramFiles(Path... programFiles) {
    this.programFiles.addAll(Arrays.asList(programFiles));
    return this;
  }

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

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

  public L8TestBuilder addLibraryFiles(Collection<Path> libraryFiles) {
    this.libraryFiles.addAll(libraryFiles);
    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 addKeepRules(String keepRule) {
    this.keepRules.add(keepRule);
    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 apply(ThrowableConsumer<L8TestBuilder> thenConsumer) {
    thenConsumer.acceptWithRuntimeException(this);
    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 setProgramConsumer(ProgramConsumer programConsumer) {
    this.programConsumer = programConsumer;
    return this;
  }

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

  private ProgramConsumer computeProgramConsumer(AndroidAppConsumers sink) {
    if (programConsumer != null) {
      return programConsumer;
    }
    return backend.isCf()
        ? sink.wrapProgramConsumer(ClassFileConsumer.emptyConsumer())
        : sink.wrapProgramConsumer(DexIndexedConsumer.emptyConsumer());
  }

  public L8TestCompileResult compile() throws IOException, CompilationFailedException {
    // We wrap exceptions in a RuntimeException to call this from a lambda.
    AndroidAppConsumers sink = new AndroidAppConsumers();
    l8Builder
        .addProgramFiles(programFiles)
        .addLibraryFiles(getLibraryFiles())
        .setMode(mode)
        .setIncludeClassesChecksum(true)
        .addDesugaredLibraryConfiguration(desugaredLibrarySpecification)
        .setMinApiLevel(apiLevel.getLevel())
        .setProgramConsumer(computeProgramConsumer(sink));
    addProgramClassFileData(l8Builder);
    Path mapping = null;
    ImmutableList<String> allKeepRules = null;
    if (!keepRules.isEmpty() || generatedKeepRules != null) {
      mapping = state.getNewTempFile("mapping.txt");
      allKeepRules =
          ImmutableList.<String>builder()
              .addAll(keepRules)
              .addAll(
                  generatedKeepRules != null && !generatedKeepRules.isEmpty()
                      ? ImmutableList.of(generatedKeepRules)
                      : Collections.emptyList())
              .build();
      l8Builder
          .addProguardConfiguration(allKeepRules, Origin.unknown())
          .setProguardMapOutputPath(mapping);
    }
    ToolHelper.runL8(l8Builder.build(), optionsModifier);
    // With special program consumer we may not be able to build the resulting app.
    if (programConsumer != null) {
      return null;
    }
    assertNoUnexpectedDiagnosticMessages();
    return new L8TestCompileResult(
            sink.build(),
            apiLevel,
            allKeepRules,
            generatedKeepRules,
            mapping,
            state,
            backend.isCf() ? OutputMode.ClassFile : OutputMode.DexIndexed)
        .applyIf(finalPrefixVerification, this::validatePrefix);
  }

  private void validatePrefix(L8TestCompileResult compileResult) throws IOException {
    InternalOptions options = new InternalOptions();
    DesugaredLibrarySpecification specification =
        DesugaredLibrarySpecificationParser.parseDesugaredLibrarySpecification(
            this.desugaredLibrarySpecification,
            options.dexItemFactory(),
            options.reporter,
            true,
            apiLevel.getLevel());
    Set<String> maintainTypeOrPrefix = specification.getMaintainTypeOrPrefixForTesting();
    compileResult.inspect(
        inspector ->
            inspector.forAllClasses(
                clazz -> {
                  String finalName = clazz.getFinalName();
                  if (finalName.startsWith("java.")) {
                    assertTrue(maintainTypeOrPrefix.stream().anyMatch(finalName::startsWith));
                  } else {
                    assertTrue(finalName.startsWith("j$."));
                  }
                }));
  }

  private void assertNoUnexpectedDiagnosticMessages() {
    TestDiagnosticMessages diagnosticsMessages = state.getDiagnosticsMessages();
    diagnosticsMessages.assertNoErrors();
    List<Diagnostic> warnings = diagnosticsMessages.getWarnings();
    // We allow warnings exclusively when using the extended version for JDK11 testing.
    // In this case, all warnings should apply to org.testng.Assert types which are not present
    // in the vanilla desugared library.
    // Vanilla desugared library compilation should have no warnings.
    assertTrue(
        warnings.stream().map(Diagnostic::getDiagnosticMessage).collect(Collectors.joining()),
        warnings.isEmpty()
            || warnings.stream()
                .allMatch(warn -> warn.getDiagnosticMessage().contains("org.testng.Assert")));
    List<Diagnostic> infos = diagnosticsMessages.getInfos();
    for (Diagnostic info : infos) {
      // The rewriting confuses the generic signatures in some methods. Such signatures are never
      // used by tools (they use the non library desugared version) and are stripped when compiling
      // with R8 anyway.
      if (info instanceof UnusedProguardKeepRuleDiagnostic) {
        // The default keep rules on desugared library may be unused. They should all be defined
        // with keepclassmembers or keep,allowshrinking.
        if (info.getDiagnosticMessage().contains("keepclassmembers")
            || info.getDiagnosticMessage().contains("keep,allowshrinking")) {
          continue;
        }
        // We allow info regarding the extended version of desugared library for JDK11 testing.
        if (info.getDiagnosticMessage().contains("org.testng.")) {
          continue;
        }
        fail("Unexpected unused proguard keep rule diagnostic: " + info.getDiagnosticMessage());
      }
      // TODO(b/243483320): Investigate the Invalid signature.
      if (info.getDiagnosticMessage().contains("Invalid signature ")) {
        continue;
      }
      fail("Unexpected info diagnostic: " + info.getDiagnosticMessage());
    }
  }

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

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

  public L8TestBuilder addArtProfileForRewriting(
      ArtProfileProvider artProfileProvider, ArtProfileConsumer residualArtProfileConsumer) {
    l8Builder.addArtProfileForRewriting(artProfileProvider, residualArtProfileConsumer);
    return this;
  }
}
