// Copyright (c) 2023, 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.BaseCompilerCommandParser.parsePositiveIntArgument;

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.FlagFile;
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.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;

public class GlobalSyntheticsGeneratorCommandParser {

  private static final String LOWER_CASE_NAME = "globalsyntheticsgenerator";
  private static final String MIN_API_FLAG = "--min-api";
  private static final String CLASSFILE_DESUGARING_MODE = "--classfile";

  private static final String USAGE_MESSAGE =
      StringUtils.lines("Usage: " + LOWER_CASE_NAME + " [options] " + "where options are:");

  public static List<ParseFlagInfo> getFlags() {
    return ImmutableList.<ParseFlagInfo>builder()
        .add(ParseFlagInfoImpl.getMinApi())
        .add(ParseFlagInfoImpl.getLib())
        .add(
            ParseFlagInfoImpl.flag1(
                "--output", "<globals-file>", "Output result in <globals-file>."))
        .add(
            ParseFlagInfoImpl.flag0(
                "--classfile",
                "Generate globals for only classfile to classfile desugaring.",
                "(By default globals for both classfile and dex desugaring are generated)."))
        .add(ParseFlagInfoImpl.getVersion(LOWER_CASE_NAME))
        .add(ParseFlagInfoImpl.getHelp())
        .build();
  }

  static String getUsageMessage() {
    StringBuilder builder = new StringBuilder();
    StringUtils.appendLines(builder, USAGE_MESSAGE);
    new ParseFlagPrinter().addFlags(getFlags()).appendLinesToBuilder(builder);
    return builder.toString();
  }

  private static final Set<String> OPTIONS_WITH_ONE_PARAMETER =
      ImmutableSet.of("--output", "--lib", MIN_API_FLAG);

  public static GlobalSyntheticsGeneratorCommand.Builder parse(String[] args, Origin origin) {
    return new GlobalSyntheticsGeneratorCommandParser()
        .parse(args, origin, GlobalSyntheticsGeneratorCommand.builder());
  }

  public static GlobalSyntheticsGeneratorCommand.Builder parse(
      String[] args, Origin origin, DiagnosticsHandler handler) {
    return new GlobalSyntheticsGeneratorCommandParser()
        .parse(args, origin, GlobalSyntheticsGeneratorCommand.builder(handler));
  }

  private GlobalSyntheticsGeneratorCommand.Builder parse(
      String[] args, Origin origin, GlobalSyntheticsGeneratorCommand.Builder builder) {
    Path outputPath = null;
    boolean hasDefinedApiLevel = false;
    String[] expandedArgs = FlagFile.expandFlagFiles(args, builder::error);
    for (int i = 0; i < expandedArgs.length; i++) {
      String arg = expandedArgs[i].trim();
      String nextArg = 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] + ".", origin));
          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("--output")) {
        if (outputPath != null) {
          builder.error(
              new StringDiagnostic(
                  "Cannot output both to '" + outputPath + "' and '" + nextArg + "'", origin));
          continue;
        }
        outputPath = Paths.get(nextArg);
      } else if (arg.equals(MIN_API_FLAG)) {
        if (hasDefinedApiLevel) {
          builder.error(
              new StringDiagnostic("Cannot set multiple " + MIN_API_FLAG + " options", origin));
        } else {
          parsePositiveIntArgument(
              builder::error, MIN_API_FLAG, nextArg, origin, builder::setMinApiLevel);
          hasDefinedApiLevel = true;
        }
      } else if (arg.equals("--lib")) {
        builder.addLibraryFiles(Paths.get(nextArg));
      } else if (arg.equals(CLASSFILE_DESUGARING_MODE)) {
        builder.setClassfileDesugaringOnly(true);
      } else if (arg.startsWith("--")) {
        builder.error(new StringDiagnostic("Unknown option: " + arg, origin));
      }
    }
    if (outputPath == null) {
      outputPath = Paths.get(".");
    }
    return builder.setGlobalSyntheticsOutput(outputPath);
  }
}
