// 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.ParseFlagInfoImpl.flag0;
import static com.android.tools.r8.ParseFlagInfoImpl.flag1;
import static com.android.tools.r8.ParseFlagInfoImpl.flag2;

import com.android.tools.r8.StringConsumer.FileConsumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.profile.art.ArtProfileConsumerUtils;
import com.android.tools.r8.profile.art.ArtProfileProviderUtils;
import com.android.tools.r8.profile.startup.StartupProfileProviderUtils;
import com.android.tools.r8.utils.ArchiveResourceProvider;
import com.android.tools.r8.utils.FlagFile;
import com.android.tools.r8.utils.MapIdTemplateProvider;
import com.android.tools.r8.utils.SourceFileTemplateProvider;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class R8CommandParser extends BaseCompilerCommandParser<R8Command, R8Command.Builder> {

  static final String ISOLATED_SPLITS_FLAG = "--isolated-splits";

  // Note: this must be a super-set of OPTIONS_WITH_TWO_PARAMETERS.
  private static final Set<String> OPTIONS_WITH_ONE_PARAMETER =
      ImmutableSet.of(
          "--output",
          "--lib",
          "--classpath",
          MIN_API_FLAG,
          "--main-dex-rules",
          "--main-dex-list",
          "--feature",
          "--android-resources",
          "--main-dex-list-output",
          "--pg-conf",
          "--pg-conf-output",
          "--pg-map",
          "--pg-map-output",
          "--partition-map-output",
          "--desugared-lib",
          "--desugared-lib-pg-conf-output",
          "--map-id-template",
          "--source-file-template",
          ART_PROFILE_FLAG,
          STARTUP_PROFILE_FLAG,
          THREAD_COUNT_FLAG);

  // Note: this must be a subset of OPTIONS_WITH_ONE_PARAMETER.
  private static final Set<String> OPTIONS_WITH_TWO_PARAMETERS =
      ImmutableSet.of(ART_PROFILE_FLAG, "--feature", "--android-resources");

  // Due to the family of flags (for assertions and diagnostics) we can't base the one/two args
  // on this setup of flags. Thus, the flag collection just encodes the descriptive content.
  static List<ParseFlagInfoImpl> getFlags() {
    return ImmutableList.<ParseFlagInfoImpl>builder()
        .add(ParseFlagInfoImpl.getRelease(true))
        .add(ParseFlagInfoImpl.getDebug(false))
        .add(ParseFlagInfoImpl.getDex(true))
        .add(ParseFlagInfoImpl.getClassfile())
        .add(ParseFlagInfoImpl.getOutput())
        .add(ParseFlagInfoImpl.getLib())
        .add(ParseFlagInfoImpl.getClasspath())
        .add(ParseFlagInfoImpl.getMinApi())
        .add(flag0("--pg-compat", "Compile with R8 in Proguard compatibility mode."))
        .add(ParseFlagInfoImpl.getPgConf())
        .add(flag1("--pg-conf-output", "<file>", "Output the collective configuration to <file>."))
        .add(
            ParseFlagInfoImpl.flag1(
                "--pg-map",
                "<file>",
                "Use <file> as a mapping file for distribution "
                    + "and composition with output mapping file."))
        .add(ParseFlagInfoImpl.getPgMapOutput())
        .add(ParseFlagInfoImpl.getPartitionMapOutput())
        .add(ParseFlagInfoImpl.getDesugaredLib())
        .add(
            flag1(
                "--desugared-lib-pg-conf-output",
                "<file>",
                "Output the Proguard configuration for L8 to <file>."))
        .add(flag0("--no-tree-shaking", "Force disable tree shaking of unreachable classes."))
        .add(flag0("--no-minification", "Force disable minification of names."))
        .add(flag0("--no-data-resources", "Ignore all data resources."))
        .add(flag0("--no-desugaring", "Force disable desugaring."))
        .add(ParseFlagInfoImpl.getMainDexRules())
        .add(ParseFlagInfoImpl.getMainDexList())
        .add(
            flag2(
                "--android-resources",
                "<input>",
                "<output>",
                "Add android resource input and output to be used in resource shrinking. Both ",
                "input and output must be specified."))
        .add(
            flag2(
                "--feature",
                "<input>[:|;<res-input>]",
                "<output>[:|;<res-output>]",
                "Add feature <input> file to <output> file. Several ",
                "occurrences can map to the same output. If <res-input> and <res-output> are ",
                "specified use these as resource shrinker input and output. Separator is : on ",
                "linux/mac, ; on windows. It is possible to supply resource only features by ",
                " using an empty string for <input> and <output>, e.g. --feature :in.ap_ :out.ap_"))
        .add(ParseFlagInfoImpl.getIsolatedSplits())
        .add(flag1("--main-dex-list-output", "<file>", "Output the full main-dex list in <file>."))
        .addAll(ParseFlagInfoImpl.getAssertionsFlags())
        .add(ParseFlagInfoImpl.getThreadCount())
        .add(ParseFlagInfoImpl.getMapDiagnostics())
        .add(
            flag1(
                "--map-id-template",
                "<template>",
                "Set the map-id to <template>.",
                "The <template> can reference the variables:",
                "  %MAP_HASH: compiler generated mapping hash."))
        .add(
            flag1(
                "--source-file-template",
                "<template>",
                "Set all source-file attributes to <template>",
                "The <template> can reference the variables:",
                "  %MAP_ID: map id (e.g., value of --map-id-template).",
                "  %MAP_HASH: compiler generated mapping hash."))
        .add(ParseFlagInfoImpl.getAndroidPlatformBuild())
        .add(ParseFlagInfoImpl.getArtProfile())
        .add(ParseFlagInfoImpl.getStartupProfile())
        .add(ParseFlagInfoImpl.getVersion("r8"))
        .add(ParseFlagInfoImpl.getHelp())
        .build();
  }

  static String getUsageMessage() {
    StringBuilder builder = new StringBuilder();
    StringUtils.appendLines(
        builder,
        "Usage: r8 [options] [@<argfile>] <input-files>",
        " where <input-files> are any combination class, zip, or jar files",
        " and each <argfile> is a file containing additional arguments (one per line)",
        " and options are:");
    new ParseFlagPrinter().addFlags(ImmutableList.copyOf(getFlags())).appendLinesToBuilder(builder);
    return builder.toString();
  }

  // Internal state to verify parsing properties not enforced by the builder.
  private static class ParseState {
    CompilationMode mode = null;
    OutputMode outputMode = null;
    Path outputPath = null;
    boolean hasDefinedApiLevel = false;
    private boolean includeDataResources = true;
  }

  /**
   * Parse the R8 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 R8 command builder with state set up according to parsed command line.
   */
  public static R8Command.Builder parse(String[] args, Origin origin) {
    return new R8CommandParser().parse(args, origin, R8Command.builder());
  }

  /**
   * Parse the R8 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 R8 command builder with state set up according to parsed command line.
   */
  public static R8Command.Builder parse(String[] args, Origin origin, DiagnosticsHandler handler) {
    return new R8CommandParser().parse(args, origin, R8Command.builder(handler));
  }

  private R8Command.Builder parse(String[] args, Origin origin, R8Command.Builder builder) {
    ParseState state = new ParseState();
    parse(args, origin, builder, state);
    if (state.mode != null) {
      builder.setMode(state.mode);
    }
    Path outputPath = state.outputPath != null ? state.outputPath : Paths.get(".");
    OutputMode outputMode = state.outputMode != null ? state.outputMode : OutputMode.DexIndexed;
    builder.setOutput(outputPath, outputMode, state.includeDataResources);
    builder.setEnableExperimentalMissingLibraryApiModeling(true);
    return builder;
  }

  private void parse(
      String[] args, Origin argsOrigin, R8Command.Builder builder, ParseState state) {
    String[] expandedArgs = FlagFile.expandFlagFiles(args, builder::error);
    FeatureSplitConfigCollector featureSplitConfigCollector = new FeatureSplitConfigCollector();
    for (int i = 0; i < expandedArgs.length; i++) {
      String arg = expandedArgs[i].trim();
      String nextArg = null;
      String nextNextArg = null;
      if (OPTIONS_WITH_ONE_PARAMETER.contains(arg)) {
        if (++i < expandedArgs.length) {
          nextArg = expandedArgs[i];
        } else {
          builder.error(
              new StringDiagnostic(
                  "Missing parameter for " + expandedArgs[i - 1] + ".", argsOrigin));
          break;
        }
        if (OPTIONS_WITH_TWO_PARAMETERS.contains(arg)) {
          if (++i < expandedArgs.length) {
            nextNextArg = expandedArgs[i];
          } else {
            builder.error(
                new StringDiagnostic(
                    "Missing parameter for " + expandedArgs[i - 2] + ".", argsOrigin));
            break;
          }
        }
      }
      if (arg.length() == 0) {
        continue;
      } else if (arg.equals("--help")) {
        builder.setPrintHelp(true);
      } else if (arg.equals("--version")) {
        builder.setPrintVersion(true);
      } else if (arg.equals("--debug")) {
        if (state.mode == CompilationMode.RELEASE) {
          builder.error(
              new StringDiagnostic(
                  "Cannot compile in both --debug and --release mode.", argsOrigin));
        }
        state.mode = CompilationMode.DEBUG;
      } else if (arg.equals("--release")) {
        if (state.mode == CompilationMode.DEBUG) {
          builder.error(
              new StringDiagnostic(
                  "Cannot compile in both --debug and --release mode.", argsOrigin));
        }
        state.mode = CompilationMode.RELEASE;
      } else if (arg.equals("--pg-compat")) {
        builder.setProguardCompatibility(true);
      } else if (arg.equals("--dex")) {
        if (state.outputMode == OutputMode.ClassFile) {
          builder.error(
              new StringDiagnostic(
                  "Cannot compile in both --dex and --classfile output mode.", argsOrigin));
        }
        state.outputMode = OutputMode.DexIndexed;
      } else if (arg.equals("--classfile")) {
        if (state.outputMode == OutputMode.DexIndexed) {
          builder.error(
              new StringDiagnostic(
                  "Cannot compile in both --dex and --classfile output mode.", argsOrigin));
        }
        state.outputMode = OutputMode.ClassFile;
      } else if (arg.equals("--output")) {
        if (state.outputPath != null) {
          builder.error(
              new StringDiagnostic(
                  "Cannot output both to '"
                      + state.outputPath.toString()
                      + "' and '"
                      + nextArg
                      + "'",
                  argsOrigin));
        }
        state.outputPath = Paths.get(nextArg);
      } else if (arg.equals("--lib")) {
        addLibraryArgument(builder, argsOrigin, nextArg);
      } else if (arg.equals("--classpath")) {
        builder.addClasspathFiles(Paths.get(nextArg));
      } else if (arg.equals(MIN_API_FLAG)) {
        if (state.hasDefinedApiLevel) {
          builder.error(
              new StringDiagnostic("Cannot set multiple " + MIN_API_FLAG + " options", argsOrigin));
        } else {
          parsePositiveIntArgument(
              builder::error, MIN_API_FLAG, nextArg, argsOrigin, builder::setMinApiLevel);
          state.hasDefinedApiLevel = true;
        }
      } else if (arg.equals(THREAD_COUNT_FLAG)) {
        parsePositiveIntArgument(
            builder::error, THREAD_COUNT_FLAG, nextArg, argsOrigin, builder::setThreadCount);
      } else if (arg.equals("--no-tree-shaking")) {
        builder.setDisableTreeShaking(true);
      } else if (arg.equals("--no-minification")) {
        builder.setDisableMinification(true);
      } else if (arg.equals("--no-desugaring")) {
        builder.setDisableDesugaring(true);
      } else if (arg.equals("--main-dex-rules")) {
        builder.addMainDexRulesFiles(Paths.get(nextArg));
      } else if (arg.equals("--android-resources")) {
        Path inputPath = Paths.get(nextArg);
        Path outputPath = Paths.get(nextNextArg);
        builder.setAndroidResourceProvider(new ArchiveProtoAndroidResourceProvider(inputPath));
        builder.setAndroidResourceConsumer(
            new ArchiveProtoAndroidResourceConsumer(outputPath, inputPath));
        // In the CLI we default to optimized resource shrinking.
        builder.setResourceShrinkerConfiguration(b -> b.enableOptimizedShrinkingWithR8().build());
      } else if (arg.equals("--feature")) {
        featureSplitConfigCollector.addInputOutput(nextArg, nextNextArg);
      } else if (arg.equals(ISOLATED_SPLITS_FLAG)) {
        builder.setEnableIsolatedSplits(true);
      } else if (arg.equals("--main-dex-list")) {
        builder.addMainDexListFiles(Paths.get(nextArg));
      } else if (arg.equals("--main-dex-list-output")) {
        builder.setMainDexListOutputPath(Paths.get(nextArg));
      } else if (arg.equals("--optimize-multidex-for-linearalloc")) {
        builder.setOptimizeMultidexForLinearAlloc(true);
      } else if (arg.equals("--pg-conf")) {
        builder.addProguardConfigurationFiles(Paths.get(nextArg));
      } else if (arg.equals("--pg-conf-output")) {
        FileConsumer consumer = new FileConsumer(Paths.get(nextArg));
        builder.setProguardConfigurationConsumer(consumer);
      } else if (arg.equals("--pg-map")) {
        builder.setProguardMapInputFile(Paths.get(nextArg));
      } else if (arg.equals("--pg-map-output")) {
        builder.setProguardMapOutputPath(Paths.get(nextArg));
      } else if (arg.equals("--partition-map-output")) {
        builder.setPartitionMapOutputPath(Paths.get(nextArg));
      } else if (arg.equals("--desugared-lib")) {
        builder.addDesugaredLibraryConfiguration(StringResource.fromFile(Paths.get(nextArg)));
      } else if (arg.equals("--desugared-lib-pg-conf-output")) {
        StringConsumer consumer = new StringConsumer.FileConsumer(Paths.get(nextArg));
        builder.setDesugaredLibraryKeepRuleConsumer(consumer);
      } else if (arg.equals("--no-data-resources")) {
        state.includeDataResources = false;
      } else if (arg.equals("--map-id-template")) {
        builder.setMapIdProvider(MapIdTemplateProvider.create(nextArg, builder.getReporter()));
      } else if (arg.equals("--source-file-template")) {
        builder.setSourceFileProvider(
            SourceFileTemplateProvider.create(nextArg, builder.getReporter()));
      } else if (arg.equals("--android-platform-build")) {
        builder.setAndroidPlatformBuild(true);
      } else if (arg.equals(ART_PROFILE_FLAG)) {
        Path artProfilePath = Paths.get(nextArg);
        Path rewrittenArtProfilePath = Paths.get(nextNextArg);
        builder.addArtProfileForRewriting(
            ArtProfileProviderUtils.createFromHumanReadableArtProfile(artProfilePath),
            ArtProfileConsumerUtils.create(rewrittenArtProfilePath));
      } else if (arg.equals(STARTUP_PROFILE_FLAG)) {
        Path startupProfilePath = Paths.get(nextArg);
        builder.addStartupProfileProviders(
            StartupProfileProviderUtils.createFromHumanReadableArtProfile(startupProfilePath));
      } else if (arg.startsWith("--")) {
        if (tryParseAssertionArgument(builder, arg, argsOrigin)) {
          continue;
        }
        int argsConsumed = tryParseMapDiagnostics(builder, arg, expandedArgs, i, argsOrigin);
        if (argsConsumed >= 0) {
          i += argsConsumed;
          continue;
        }
        argsConsumed = tryParseDump(builder, arg, expandedArgs, i, argsOrigin);
        if (argsConsumed >= 0) {
          i += argsConsumed;
          continue;
        }
        builder.error(new StringDiagnostic("Unknown option: " + arg, argsOrigin));
      } else if (arg.startsWith("@")) {
        builder.error(new StringDiagnostic("Recursive @argfiles are not supported: ", argsOrigin));
      } else {
        builder.addProgramFiles(Paths.get(arg));
      }
    }
    addFeatureSplitConfigs(
        builder, featureSplitConfigCollector.getConfigs(), state.includeDataResources);
  }

  private void addFeatureSplitConfigs(
      R8Command.Builder builder,
      Collection<FeatureSplitConfig> featureSplitConfigs,
      boolean includeDataResources) {
    for (FeatureSplitConfig featureSplitConfig : featureSplitConfigs) {
      builder.addFeatureSplit(
          featureSplitGenerator -> {
            if (featureSplitConfig.outputJar != null) {
              featureSplitGenerator.setProgramConsumer(
                  builder.createProgramOutputConsumer(
                      featureSplitConfig.outputJar, OutputMode.DexIndexed, includeDataResources));
            }
            for (Path inputPath : featureSplitConfig.inputJars) {
              featureSplitGenerator.addProgramResourceProvider(
                  ArchiveResourceProvider.fromArchive(inputPath, false));
            }
            if (featureSplitConfig.inputResources != null) {
              featureSplitGenerator.setAndroidResourceProvider(
                  new ArchiveProtoAndroidResourceProvider(
                      featureSplitConfig.inputResources,
                      new PathOrigin(featureSplitConfig.inputResources)));
            }
            if (featureSplitConfig.outputResources != null) {
              featureSplitGenerator.setAndroidResourceConsumer(
                  new ArchiveProtoAndroidResourceConsumer(
                      featureSplitConfig.outputResources, featureSplitConfig.inputResources));
            }
            return featureSplitGenerator.build();
          });
    }
  }

  // Represents a set of paths parsed from a string that may contain a ":" (";" on windows).
  // Supported examples are:
  //   pathA -> first = pathA, second = null
  //   pathA:pathB -> first = pathA, second = pathB
  //   :pathB -> first = null, second = pathB
  //   pathA: -> first = pathA, second = null
  private static class PossibleDoublePath {

    public final Path first;
    public final Path second;

    private PossibleDoublePath(Path first, Path second) {
      this.first = first;
      this.second = second;
    }

    public static PossibleDoublePath parse(String input) {
      Path first = null, second = null;
      List<String> inputSplit = StringUtils.split(input, File.pathSeparatorChar);
      if (inputSplit.size() == 0 || inputSplit.size() > 2) {
        throw new IllegalArgumentException("Feature input/output takes one or two paths.");
      }
      String firstString = inputSplit.get(0);
      if (!firstString.isEmpty()) {
        first = Paths.get(firstString);
      }
      if (inputSplit.size() == 2) {
        // "a:".split() gives just ["a"], so we should never get here if we don't have
        // a second string. ":b".split gives ["", "b"] which is handled for first above.
        assert inputSplit.get(1).length() > 0;
        second = Paths.get(inputSplit.get(1));
      }
      return new PossibleDoublePath(first, second);
    }
  }

  private static class FeatureSplitConfig {
    private List<Path> inputJars = new ArrayList<>();
    private Path inputResources;
    private Path outputResources;
    private Path outputJar;
  }

  private static class FeatureSplitConfigCollector {

    private List<FeatureSplitConfig> resourceOnlySplits = new ArrayList<>();
    private Map<Path, FeatureSplitConfig> withCodeSplits = new HashMap<>();

    public void addInputOutput(String input, String output) {
      PossibleDoublePath inputPaths = PossibleDoublePath.parse(input);
      PossibleDoublePath outputPaths = PossibleDoublePath.parse(output);
      FeatureSplitConfig featureSplitConfig;
      if (outputPaths.first != null) {
        featureSplitConfig =
            withCodeSplits.computeIfAbsent(outputPaths.first, k -> new FeatureSplitConfig());
        featureSplitConfig.outputJar = outputPaths.first;
        // We support adding resources independently of the input jars, which later --feature
        // can add, so we might have no input jars here, example:
        //  ... --feature :input_feature.ap_ out.jar:out_feature.ap_ --feature in.jar out.jar
        if (inputPaths.first != null) {
          featureSplitConfig.inputJars.add(inputPaths.first);
        }
      } else {
        featureSplitConfig = new FeatureSplitConfig();
        resourceOnlySplits.add(featureSplitConfig);
      }
      if (Objects.isNull(inputPaths.second) != Objects.isNull(outputPaths.second)) {
        throw new IllegalArgumentException(
            "Both input and output for feature resources must be provided");
      }
      featureSplitConfig.inputResources = inputPaths.second;
      featureSplitConfig.outputResources = outputPaths.second;
    }

    public Collection<FeatureSplitConfig> getConfigs() {
      ArrayList<FeatureSplitConfig> featureSplitConfigs = new ArrayList<>(resourceOnlySplits);
      featureSplitConfigs.addAll(withCodeSplits.values());
      return featureSplitConfigs;
    }
  }
}
