// 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.BaseCompilerCommandUtils.createProgramOutputConsumer;
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.FileUtils;
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.io.IOException;
import java.io.UncheckedIOException;
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 BLAST_RADIUS_OUTPUT_FLAG = "--blast-radius-output";
  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_FLAG,
          "--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",
          "--map-id-template",
          "--source-file-template",
          ART_PROFILE_FLAG,
          STARTUP_PROFILE_FLAG,
          THREAD_COUNT_FLAG,
          BLAST_RADIUS_OUTPUT_FLAG,
          BUILD_METADATA_OUTPUT_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(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 hasBlastRadiusOutput = false;
    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);
    }
    OutputMode outputMode = state.outputMode != null ? state.outputMode : OutputMode.DexIndexed;
    if (state.hasBlastRadiusOutput
        && state.outputPath == null
        && outputMode == OutputMode.DexIndexed) {
      builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
    } else {
      Path outputPath = state.outputPath != null ? state.outputPath : Paths.get(".");
      builder.setOutput(outputPath, outputMode, state.includeDataResources);
    }
    builder.setEnableExperimentalMissingLibraryApiModeling(true);
    return builder;
  }

  private void parse(
      String[] args, Origin argsOrigin, R8Command.Builder builder, ParseState state) {
    Path blastRadiusOutputPath = null;
    Path buildMetadataOutputPath = null;
    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_FLAG)) {
        addLibraryArgument(builder, nextArg, argsOrigin);
      } 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("--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.equals(BLAST_RADIUS_OUTPUT_FLAG)) {
        if (blastRadiusOutputPath != null) {
          builder.error(
              new StringDiagnostic(
                  "Cannot output blast radius to both '"
                      + blastRadiusOutputPath
                      + "' and '"
                      + nextArg
                      + "'",
                  argsOrigin));
          continue;
        }
        blastRadiusOutputPath = Paths.get(nextArg);
        state.hasBlastRadiusOutput = true;
      } else if (arg.equals(BUILD_METADATA_OUTPUT_FLAG)) {
        if (buildMetadataOutputPath != null) {
          builder.error(
              new StringDiagnostic(
                  "Cannot output build metadata to both '"
                      + buildMetadataOutputPath
                      + "' and '"
                      + nextArg
                      + "'",
                  argsOrigin));
          continue;
        }
        buildMetadataOutputPath = Paths.get(nextArg);
      } 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);
    if (blastRadiusOutputPath != null) {
      builder.setBlastRadiusOutputPath(blastRadiusOutputPath);
    }
    if (buildMetadataOutputPath != null) {
      final Path finalBuildMetadataOutputPath = buildMetadataOutputPath;
      builder.setBuildMetadataConsumer(
          buildMetadata -> {
            try {
              FileUtils.writeTextFile(finalBuildMetadataOutputPath, buildMetadata.toJson());
            } catch (IOException e) {
              throw new UncheckedIOException(e);
            }
          });
    }
  }

  private void addFeatureSplitConfigs(
      R8Command.Builder builder,
      Collection<FeatureSplitConfig> featureSplitConfigs,
      boolean includeDataResources) {
    for (FeatureSplitConfig featureSplitConfig : featureSplitConfigs) {
      builder.addFeatureSplit(
          featureSplitGenerator -> {
            if (featureSplitConfig.outputJar != null) {
              featureSplitGenerator.setProgramConsumer(
                  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;
    }
  }
}
