// 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.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.Pair;
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.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,
      int 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) {
    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);
    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(getMinApiLevel()));
    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;

    internal.horizontalClassMergerOptions().disable();

    assert internal.desugarState == DesugarState.ON;
    assert internal.enableInheritanceClassInDexDistributor;
    internal.enableInheritanceClassInDexDistributor = false;

    internal.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.");
    }

    @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(getMinApiLevel())
                .setMode(getMode())
                .setIncludeClassesChecksum(getIncludeClassesChecksum())
                .setDexClassChecksumFilter(getDexClassChecksumFilter())
                .setProgramConsumer(getProgramConsumer());
        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();
        r8Command = r8Builder.makeCommand();
      } else if (!(getProgramConsumer() instanceof ClassFileConsumer)) {
        l8CfConsumer = new InMemoryJarContent();
        D8Command.Builder d8Builder =
            D8Command.builder(getReporter())
                .addProgramResourceProvider((ProgramResourceProvider) l8CfConsumer)
                .setSynthesizedClassesPrefix(
                    desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix())
                .setMinApiLevel(getMinApiLevel())
                .setMode(getMode())
                .setIncludeClassesChecksum(getIncludeClassesChecksum())
                .setDexClassChecksumFilter(getDexClassChecksumFilter())
                .setProgramConsumer(getProgramConsumer())
                .setEnableRewritingOfArtProfilesIsNopCheck();
        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(),
          getMinApiLevel(),
          getReporter(),
          getIncludeClassesChecksum(),
          getDexClassChecksumFilter(),
          desugaredLibrarySpecification,
          getAssertionsConfiguration(),
          getOutputInspections(),
          getThreadCount(),
          getDumpInputFlags(),
          getMapIdProvider(),
          getClassConflictResolver(),
          getCancelCompilationChecker(),
          factory);
    }
  }

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