// 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.utils.InternalOptions.DETERMINISTIC_DEBUGGING;

import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.inspector.Inspector;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.partial.R8PartialCompilationConfiguration;
import com.android.tools.r8.profile.art.ArtProfileForRewriting;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
import com.android.tools.r8.utils.DumpInputFlags;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.ProgramClassCollection;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.UncheckedApiLevel;
import com.android.tools.r8.utils.internal.collections.Pair;
import com.google.common.collect.ImmutableList;
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.BiPredicate;
import java.util.function.Consumer;

/** Immutable command structure for an invocation of the {@link L8} library compiler. */
@KeepForApi
public final class L8Command extends BaseCompilerCommand {

  private final D8Command d8Command;
  private final R8Command r8Command;
  private final DesugaredLibrarySpecification desugaredLibrarySpecification;
  private final DexItemFactory factory;

  boolean isShrinking() {
    return r8Command != null;
  }

  D8Command getD8Command() {
    return d8Command;
  }

  R8Command getR8Command() {
    return r8Command;
  }

  /**
   * Parse the L8 command-line.
   *
   * <p>Parsing will set the supplied options or their default value if they have any.
   *
   * @param args Command-line arguments array.
   * @param origin Origin description of the command-line arguments.
   * @return L8 command builder with state set up according to parsed command line.
   */
  public static Builder parse(String[] args, Origin origin) {
    return L8CommandParser.parse(args, origin);
  }

  /**
   * Parse the L8 command-line.
   *
   * <p>Parsing will set the supplied options or their default value if they have any.
   *
   * @param args Command-line arguments array.
   * @param origin Origin description of the command-line arguments.
   * @param handler Custom defined diagnostics handler.
   * @return L8 command builder with state set up according to parsed command line.
   */
  public static Builder parse(String[] args, Origin origin, DiagnosticsHandler handler) {
    return L8CommandParser.parse(args, origin, handler);
  }

  private L8Command(
      R8Command r8Command,
      D8Command d8Command,
      AndroidApp inputApp,
      CompilationMode mode,
      ProgramConsumer programConsumer,
      StringConsumer mainDexListConsumer,
      UncheckedApiLevel minApiLevel,
      Reporter diagnosticsHandler,
      boolean encodeChecksum,
      BiPredicate<String, Long> dexClassChecksumFilter,
      DesugaredLibrarySpecification desugaredLibrarySpecification,
      List<AssertionsConfiguration> assertionsConfiguration,
      List<Consumer<Inspector>> outputInspections,
      int threadCount,
      DumpInputFlags dumpInputFlags,
      MapIdProvider mapIdProvider,
      ClassConflictResolver classConflictResolver,
      CancelCompilationChecker cancelCompilationChecker,
      DexItemFactory factory,
      Path apiDatabasePath,
      boolean enableVerboseSyntheticNames) {
    super(
        inputApp,
        mode,
        programConsumer,
        mainDexListConsumer,
        minApiLevel,
        diagnosticsHandler,
        DesugarState.ON,
        false,
        encodeChecksum,
        dexClassChecksumFilter,
        assertionsConfiguration,
        outputInspections,
        threadCount,
        dumpInputFlags,
        mapIdProvider,
        null,
        false,
        Collections.emptyList(),
        Collections.emptyList(),
        classConflictResolver,
        cancelCompilationChecker,
        enableVerboseSyntheticNames,
        apiDatabasePath);
    this.d8Command = d8Command;
    this.r8Command = r8Command;
    this.desugaredLibrarySpecification = desugaredLibrarySpecification;
    this.factory = factory;
  }

  private L8Command(boolean printHelp, boolean printVersion) {
    super(printHelp, printVersion);
    r8Command = null;
    d8Command = null;
    desugaredLibrarySpecification = null;
    factory = null;
  }

  protected static class DefaultL8DiagnosticsHandler implements DiagnosticsHandler {

    @Override
    public void error(Diagnostic error) {
      if (error instanceof DexFileOverflowDiagnostic) {
        DexFileOverflowDiagnostic overflowDiagnostic = (DexFileOverflowDiagnostic) error;
        DiagnosticsHandler.super.error(
            new StringDiagnostic(
                overflowDiagnostic.getDiagnosticMessage()
                    + ". Library too large. L8 can only produce a single .dex file"));
        return;
      }
      DiagnosticsHandler.super.error(error);
    }
  }

  public static Builder builder() {
    return new Builder();
  }

  public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
    return new Builder(diagnosticsHandler);
  }

  @Override
  List<ArtProfileForRewriting> getArtProfilesForRewriting() {
    if (getD8Command() != null) {
      return getD8Command().getArtProfilesForRewriting();
    }
    if (getR8Command() != null) {
      return getR8Command().getArtProfilesForRewriting();
    }
    return Collections.emptyList();
  }

  @Override
  InternalOptions getInternalOptions() {
    InternalOptions internal = new InternalOptions(factory, getReporter());
    assert !internal.debug;
    internal.debug = getMode() == CompilationMode.DEBUG;
    assert internal.mainDexListConsumer == null;
    assert !internal.minimalMainDex;
    internal.setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(getUncheckedMinApiLevel()));
    assert !internal.intermediate;
    assert internal.retainCompileTimeAnnotations;
    internal.programConsumer = getProgramConsumer();
    assert internal.programConsumer instanceof ClassFileConsumer;

    // Assert and fixup defaults.
    assert !internal.isShrinking();
    assert !internal.isMinifying();
    assert !internal.passthroughDexCode;

    // Assert some of R8 optimizations are disabled.
    assert !internal.enableClassInlining;
    assert !internal.enableEnumValueOptimization;
    assert !internal.outline.enabled;
    assert !internal.enableTreeShakingOfLibraryMethodOverrides;

    assert internal.desugarState == DesugarState.ON;
    assert internal.enableInheritanceClassInDexDistributor;
    internal.enableInheritanceClassInDexDistributor = false;
    internal.desugarSpecificOptions().enableVerboseSyntheticNames = enableVerboseSyntheticNames;

    internal
        .getLibraryDesugaringOptions()
        .configureDesugaredLibrary(
            desugaredLibrarySpecification,
            desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix());

    // Default is to remove all javac generated assertion code when generating dex.
    assert internal.assertionsConfiguration == null;
    internal.assertionsConfiguration =
        new AssertionConfigurationWithDefault(
            AssertionsConfiguration.builder(getReporter())
                .setCompileTimeDisable()
                .setScopeAll()
                .build(),
            getAssertionsConfiguration());

    internal.programClassConflictResolver =
        ProgramClassCollection.wrappedConflictResolver(
            getClassConflictResolver(), internal.reporter);

    internal.cancelCompilationChecker = getCancelCompilationChecker();

    if (!DETERMINISTIC_DEBUGGING) {
      assert internal.threadCount == ThreadUtils.NOT_SPECIFIED;
      internal.threadCount = getThreadCount();
    }

    // Disable global optimizations.
    internal.disableGlobalOptimizations();
    internal
        .apiModelingOptions()
        .disableApiCallerIdentification()
        .disableOutlining()
        .disableStubbingOfClasses();

    internal.setDumpInputFlags(getDumpInputFlags());
    internal.dumpOptions = dumpOptions();

    return internal;
  }

  /**
   * Builder for constructing a L8Command.
   *
   * <p>A builder is obtained by calling {@link L8Command#builder}.
   */
  @KeepForApi
  public static class Builder extends BaseCompilerCommand.Builder<L8Command, Builder> {

    private final List<Pair<List<String>, Origin>> proguardConfigStrings = new ArrayList<>();
    private final List<Path> proguardConfigFiles = new ArrayList<>();

    private Builder() {
      this(new DefaultL8DiagnosticsHandler());
    }

    private Builder(DiagnosticsHandler diagnosticsHandler) {
      super(diagnosticsHandler);
    }

    public boolean isShrinking() {
      // Answers true if keep rules, even empty, are provided.
      return !proguardConfigStrings.isEmpty() || !proguardConfigFiles.isEmpty();
    }

    @Override
    Builder self() {
      return this;
    }

    @Override
    CompilationMode defaultCompilationMode() {
      return CompilationMode.DEBUG;
    }

    /** Add proguard configuration-file resources. */
    public Builder addProguardConfigurationFiles(Path... paths) {
      Collections.addAll(proguardConfigFiles, paths);
      return self();
    }

    /** Add proguard configuration-file resources. */
    public Builder addProguardConfigurationFiles(List<Path> paths) {
      proguardConfigFiles.addAll(paths);
      return self();
    }

    /** Add proguard configuration. */
    public Builder addProguardConfiguration(List<String> lines, Origin origin) {
      proguardConfigStrings.add(new Pair<>(lines, origin));
      return self();
    }

    /**
     * Set an output destination to which proguard-map content should be written.
     *
     * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
     * #setProguardMapConsumer}. Note that any subsequent call to this method or {@link
     * #setProguardMapConsumer} will override the previous setting.
     *
     * @param proguardMapOutput File-system path to write output at.
     */
    @Override
    public Builder setProguardMapOutputPath(Path proguardMapOutput) {
      return super.setProguardMapOutputPath(proguardMapOutput);
    }

    /**
     * Set a consumer for receiving the proguard-map content.
     *
     * <p>Note that any subsequent call to this method or {@link #setProguardMapOutputPath} will
     * override the previous setting.
     *
     * @param proguardMapConsumer Consumer to receive the content once produced.
     */
    @Override
    public Builder setProguardMapConsumer(StringConsumer proguardMapConsumer) {
      return super.setProguardMapConsumer(proguardMapConsumer);
    }

    @Override
    public Builder setAndroidPlatformBuild(boolean isAndroidPlatformBuild) {
      throw getReporter().fatalError("L8 does not support configuring Android platform builds.");
    }

    /**
     * By default, L8 uses the same naming scheme for synthetic classes as javac uses for anonymous
     * inner classes. By enabling verbose synthetic names, the synthetic classes will include a
     * "$$ExternalSynthetic" marker, which includes the synthetic kind (e.g., "Lambda").
     */
    @Override
    public Builder setEnableVerboseSyntheticNames(boolean enableVerboseSyntheticNames) {
      return super.setEnableVerboseSyntheticNames(enableVerboseSyntheticNames);
    }

    @Override
    void validate() {
      if (isPrintHelp()) {
        return;
      }
      Reporter reporter = getReporter();
      boolean isGeneratingClassFiles = getProgramConsumer() instanceof ClassFileConsumer;
      if (!hasDesugaredLibraryConfiguration()) {
        reporter.error("L8 requires a desugared library configuration");
      }
      if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
        reporter.error("L8 does not support compiling to dex per class");
      }
      if (getAppBuilder().hasMainDexList()) {
        reporter.error("L8 does not support a main dex list");
      } else if (getMainDexListConsumer() != null) {
        reporter.error("L8 does not support generating a main dex list");
      }
      if (isShrinking()) {
        if (isGeneratingClassFiles) {
          reporter.error("L8 does not support shrinking when generating class files");
        }
      } else {
        if (proguardMapConsumer != null || partitionMapConsumer != null) {
          reporter.error("L8 does not support defining a map consumer when not shrinking");
        }
        if (!getArtProfilesForRewriting().isEmpty()) {
          if (isGeneratingClassFiles) {
            reporter.error(
                "L8 does not support rewriting of ART profiles when generating class files");
          } else {
            reporter.error("L8 does not impact ART profiles when generating DEX and not shrinking");
          }
        }
      }
      super.validate();
    }

    @Override
    L8Command makeCommand() {
      if (isPrintHelp() || isPrintVersion()) {
        return new L8Command(isPrintHelp(), isPrintVersion());
      }

      if (getMode() == null) {
        setMode(defaultCompilationMode());
      }

      DexItemFactory factory = new DexItemFactory();
      DesugaredLibrarySpecification desugaredLibrarySpecification =
          getDesugaredLibraryConfiguration(factory, true);

      R8Command r8Command = null;
      D8Command d8Command = null;

      AndroidApp inputs = getAppBuilder().build();
      ProgramConsumer l8CfConsumer;
      if (isShrinking()) {
        l8CfConsumer = new InMemoryJarContent();
        R8Command.Builder r8Builder =
            R8Command.builder(getReporter())
                .addProgramResourceProvider((ProgramResourceProvider) l8CfConsumer)
                .enableLegacyFullModeForKeepRules(false)
                .setSynthesizedClassesPrefix(
                    desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix())
                .setMinApiLevel(getUncheckedMinApiLevel())
                .setMode(getMode())
                .setIncludeClassesChecksum(getIncludeClassesChecksum())
                .setDexClassChecksumFilter(getDexClassChecksumFilter())
                .setProgramConsumer(getProgramConsumer())
                .setApiDatabasePath(getApiDatabasePath())
                .setEnableVerboseSyntheticNames(enableVerboseSyntheticNames);
        for (ArtProfileForRewriting artProfileForRewriting : getArtProfilesForRewriting()) {
          r8Builder.addArtProfileForRewriting(artProfileForRewriting);
        }
        for (ClassFileResourceProvider libraryResourceProvider :
            inputs.getLibraryResourceProviders()) {
          r8Builder.addLibraryResourceProvider(libraryResourceProvider);
        }
        for (Pair<List<String>, Origin> proguardConfig : proguardConfigStrings) {
          r8Builder.addProguardConfiguration(proguardConfig.getFirst(), proguardConfig.getSecond());
        }
        if (proguardMapConsumer != null) {
          r8Builder.setProguardMapConsumer(proguardMapConsumer);
        }
        if (partitionMapConsumer != null) {
          r8Builder.setPartitionMapConsumer(partitionMapConsumer);
        }
        r8Builder.addProguardConfiguration(
            desugaredLibrarySpecification.getExtraKeepRules(), Origin.unknown());
        // TODO(b/180903899): Remove rule when -dontwarn sun.misc.Unsafe is part of config.
        r8Builder.addProguardConfiguration(
            ImmutableList.of("-dontwarn sun.misc.Unsafe"), Origin.unknown());
        r8Builder.addProguardConfigurationFiles(proguardConfigFiles);
        r8Builder.setDisableDesugaring(true);
        r8Builder.skipDump();
        r8Builder.setPartialCompilationConfiguration(
            R8PartialCompilationConfiguration.disabledConfiguration());
        r8Command = r8Builder.makeCommand();
      } else if (!(getProgramConsumer() instanceof ClassFileConsumer)) {
        l8CfConsumer = new InMemoryJarContent();
        D8Command.Builder d8Builder =
            D8Command.builder(getReporter())
                .addProgramResourceProvider((ProgramResourceProvider) l8CfConsumer)
                .setSynthesizedClassesPrefix(
                    desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix())
                .setMinApiLevel(getUncheckedMinApiLevel())
                .setMode(getMode())
                .setIncludeClassesChecksum(getIncludeClassesChecksum())
                .setDexClassChecksumFilter(getDexClassChecksumFilter())
                .setProgramConsumer(getProgramConsumer())
                .setApiDatabasePath(getApiDatabasePath())
                .setEnableRewritingOfArtProfilesIsNopCheck()
                .setEnableVerboseSyntheticNames(enableVerboseSyntheticNames);
        for (ClassFileResourceProvider libraryResourceProvider :
            inputs.getLibraryResourceProviders()) {
          d8Builder.addLibraryResourceProvider(libraryResourceProvider);
        }
        d8Builder.setDisableDesugaring(true);
        d8Builder.skipDump();
        d8Command = d8Builder.makeCommand();
      } else {
        assert getProgramConsumer() instanceof ClassFileConsumer;
        l8CfConsumer = getProgramConsumer();
        d8Command = null;
      }
      return new L8Command(
          r8Command,
          d8Command,
          inputs,
          getMode(),
          l8CfConsumer,
          getMainDexListConsumer(),
          getUncheckedMinApiLevel(),
          getReporter(),
          getIncludeClassesChecksum(),
          getDexClassChecksumFilter(),
          desugaredLibrarySpecification,
          getAssertionsConfiguration(),
          getOutputInspections(),
          getThreadCount(),
          getDumpInputFlags(),
          getMapIdProvider(),
          getClassConflictResolver(),
          getCancelCompilationChecker(),
          factory,
          getApiDatabasePath(),
          enableVerboseSyntheticNames);
    }
  }

  static class InMemoryJarContent implements ClassFileConsumer, ProgramResourceProvider {

    private final List<ProgramResource> resources = new ArrayList<>();

    @Override
    public synchronized void accept(
        ByteDataView data, String descriptor, DiagnosticsHandler handler) {
      // TODO(b/139273544): Map Origin information.
      resources.add(
          ProgramResource.fromBytes(
              Origin.unknown(), Kind.CF, data.copyByteData(), Collections.singleton(descriptor)));
    }

    @Override
    public Collection<ProgramResource> getProgramResources() {
      return resources;
    }

    @Override
    public void getProgramResources(Consumer<ProgramResource> consumer) {
      resources.forEach(consumer);
    }

    @Override
    public void finished(DiagnosticsHandler handler) {}
  }

  private DumpOptions dumpOptions() {
    DumpOptions.Builder builder = DumpOptions.builder(Tool.L8).readCurrentSystemProperties();
    dumpBaseCommandOptions(builder);
    if (r8Command != null) {
      builder.setProguardConfiguration(r8Command.getInternalOptions().getProguardConfiguration());
    }
    return builder.setDesugaredLibraryConfiguration(desugaredLibrarySpecification).build();
  }
}
