// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.common.options;

import static com.google.devtools.common.options.OptionsParser.STARLARK_SKIPPED_PREFIXES;

import com.github.benmanes.caffeine.cache.CaffeineSpec;
import com.google.common.base.Ascii;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import java.time.Duration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.Nullable;

/** Some convenient converters used by blaze. Note: These are specific to blaze. */
public final class Converters {
  /**
   * The name of the flag used for shorthand aliasing in blaze. {@see
   * com.google.devtools.build.lib.analysis.config.CoreOptions#commandLineFlagAliases} for the
   * option definition.
   */
  public static final String BLAZE_ALIASING_FLAG = "flag_alias";

  private static final ImmutableSet<String> ENABLED_REPS =
      ImmutableSet.of("true", "1", "yes", "t", "y");

  private static final ImmutableSet<String> DISABLED_REPS =
      ImmutableSet.of("false", "0", "no", "f", "n");

  /** Standard converter for booleans. Accepts common shorthands/synonyms. */
  public static class BooleanConverter extends Converter.Contextless<Boolean> {
    @Override
    public Boolean convert(String input) throws OptionsParsingException {
      if (input == null) {
        return false;
      }
      input = Ascii.toLowerCase(input);
      if (ENABLED_REPS.contains(input)) {
        return true;
      }
      if (DISABLED_REPS.contains(input)) {
        return false;
      }
      throw new OptionsParsingException("'" + input + "' is not a boolean");
    }

    @Override
    public String getTypeDescription() {
      return "a boolean";
    }
  }

  /** Standard converter for Strings. */
  public static class StringConverter extends Converter.Contextless<String> {
    @Override
    public String convert(String input) {
      return input;
    }

    @Override
    public String getTypeDescription() {
      return "a string";
    }
  }

  /** Standard converter for integers. */
  public static class IntegerConverter extends Converter.Contextless<Integer> {
    @Override
    public Integer convert(String input) throws OptionsParsingException {
      try {
        return Integer.decode(input);
      } catch (NumberFormatException e) {
        throw new OptionsParsingException("'" + input + "' is not an int", e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "an integer";
    }
  }

  /** Standard converter for longs. */
  public static class LongConverter extends Converter.Contextless<Long> {
    @Override
    public Long convert(String input) throws OptionsParsingException {
      try {
        return Long.decode(input);
      } catch (NumberFormatException e) {
        throw new OptionsParsingException("'" + input + "' is not a long", e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a long integer";
    }
  }

  /** Standard converter for doubles. */
  public static class DoubleConverter extends Converter.Contextless<Double> {
    @Override
    public Double convert(String input) throws OptionsParsingException {
      try {
        return Double.parseDouble(input);
      } catch (NumberFormatException e) {
        throw new OptionsParsingException("'" + input + "' is not a double", e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a double";
    }
  }

  /** Standard converter for TriState values. */
  public static class TriStateConverter extends Converter.Contextless<TriState> {
    @Override
    public TriState convert(String input) throws OptionsParsingException {
      if (input == null) {
        return TriState.AUTO;
      }
      input = Ascii.toLowerCase(input);
      if (input.equals("auto")) {
        return TriState.AUTO;
      }
      if (ENABLED_REPS.contains(input)) {
        return TriState.YES;
      }
      if (DISABLED_REPS.contains(input)) {
        return TriState.NO;
      }
      throw new OptionsParsingException("'" + input + "' is not a boolean");
    }

    @Override
    public String getTypeDescription() {
      return "a tri-state (auto, yes, no)";
    }
  }

  /**
   * Standard "converter" for Void. Should not actually be invoked. For instance, expansion flags
   * are usually Void-typed and do not invoke the converter.
   */
  public static class VoidConverter extends Converter.Contextless<Void> {
    @Override
    public Void convert(String input) throws OptionsParsingException {
      if (input == null || input.equals("null")) {
        return null; // expected input, return is unused so null is fine.
      }
      throw new OptionsParsingException("'" + input + "' unexpected");
    }

    @Override
    public String getTypeDescription() {
      return "";
    }
  }

  /** Standard converter for the {@link java.time.Duration} type. */
  public static class DurationConverter extends Converter.Contextless<Duration> {
    private static final Pattern DURATION_REGEX = Pattern.compile("^([0-9]+)(d|h|m|s|ms)$");

    @Override
    public Duration convert(String input) throws OptionsParsingException {
      // To be compatible with the previous parser, '0' doesn't need a unit.
      if ("0".equals(input)) {
        return Duration.ZERO;
      }
      Matcher m = DURATION_REGEX.matcher(input);
      if (!m.matches()) {
        throw new OptionsParsingException("Illegal duration '" + input + "'.");
      }
      long duration = Long.parseLong(m.group(1));
      String unit = m.group(2);
      switch (unit) {
        case "d":
          return Duration.ofDays(duration);
        case "h":
          return Duration.ofHours(duration);
        case "m":
          return Duration.ofMinutes(duration);
        case "s":
          return Duration.ofSeconds(duration);
        case "ms":
          return Duration.ofMillis(duration);
        default:
          throw new IllegalStateException(
              "This must not happen. Did you update the regex without the switch case?");
      }
    }

    @Override
    public String getTypeDescription() {
      return "An immutable length of time.";
    }
  }

  // 1:1 correspondence with UsesOnlyCoreTypes.CORE_TYPES.
  /**
   * The converters that are available to the options parser by default. These are used if the
   * {@code @Option} annotation does not specify its own {@code converter}, and its type is one of
   * the following.
   */
  public static final ImmutableMap<Class<?>, Converter<?>> DEFAULT_CONVERTERS =
      new ImmutableMap.Builder<Class<?>, Converter<?>>()
          .put(String.class, new Converters.StringConverter())
          .put(int.class, new Converters.IntegerConverter())
          .put(long.class, new Converters.LongConverter())
          .put(double.class, new Converters.DoubleConverter())
          .put(boolean.class, new Converters.BooleanConverter())
          .put(TriState.class, new Converters.TriStateConverter())
          .put(Duration.class, new Converters.DurationConverter())
          .put(Void.class, new Converters.VoidConverter())
          .build();

  /**
   * Join a list of words as in English. Examples: "nothing" "one" "one or two" "one and two" "one,
   * two or three". "one, two and three". The toString method of each element is used.
   */
  static String joinEnglishList(Iterable<?> choices) {
    StringBuilder buf = new StringBuilder();
    for (Iterator<?> ii = choices.iterator(); ii.hasNext(); ) {
      Object choice = ii.next();
      if (buf.length() > 0) {
        buf.append(ii.hasNext() ? ", " : " or ");
      }
      buf.append(choice);
    }
    return buf.length() == 0 ? "nothing" : buf.toString();
  }

  /** Converter for a list of options, separated by some separator character. */
  public static class SeparatedOptionListConverter
      extends Converter.Contextless<ImmutableList<String>> {
    private final String separatorDescription;
    private final Splitter splitter;
    private final boolean allowEmptyValues;

    protected SeparatedOptionListConverter(
        char separator, String separatorDescription, boolean allowEmptyValues) {
      this.separatorDescription = separatorDescription;
      this.splitter = Splitter.on(separator);
      this.allowEmptyValues = allowEmptyValues;
    }

    @Override
    public ImmutableList<String> convert(String input) throws OptionsParsingException {
      ImmutableList<String> result =
          input.isEmpty() ? ImmutableList.of() : ImmutableList.copyOf(splitter.split(input));
      if (!allowEmptyValues && result.contains("")) {
        // If the list contains exactly the empty string, it means an empty value was passed and we
        // should instead return an empty list.
        if (result.size() == 1) {
          return ImmutableList.of();
        }

        throw new OptionsParsingException(
            "Empty values are not allowed as part of this " + getTypeDescription());
      }
      return result;
    }

    @Override
    public String getTypeDescription() {
      return separatorDescription + "-separated list of options";
    }
  }

  /**
   * Converter for options separated by some separator character, where order and count do not
   * matter, i.e. semantically it is a set, not a list.
   */
  public static class SeparatedOptionSetConverter extends SeparatedOptionListConverter {
    private final String separatorDescription;

    protected SeparatedOptionSetConverter(
        char separator, String separatorDescription, boolean allowEmptyValues) {
      super(separator, separatorDescription, allowEmptyValues);
      this.separatorDescription = separatorDescription;
    }

    @Override
    public ImmutableList<String> convert(String input) throws OptionsParsingException {
      ImmutableList<String> result = super.convert(input);
      return result.stream().distinct().sorted().collect(ImmutableList.toImmutableList());
    }

    @Override
    public String getTypeDescription() {
      return separatorDescription + "-separated set of options";
    }
  }

  /**
   * Converter for comma separated values, where
   * <li>order and multiplicity preserved
   * <li>empty values are preserved
   */
  public static class CommaSeparatedOptionListConverter extends SeparatedOptionListConverter {
    public CommaSeparatedOptionListConverter() {
      super(',', "comma", true);
    }
  }

  /**
   * Converter for comma separated values, where
   * <li>order and multiplicity preserved
   * <li>empty values are filtered out
   */
  public static class CommaSeparatedNonEmptyOptionListConverter
      extends SeparatedOptionListConverter {
    public CommaSeparatedNonEmptyOptionListConverter() {
      super(',', "comma", false);
    }
  }

  /**
   * Converter for colon separated values, where
   * <li>order and multiplicity preserved
   * <li>empty values are preserved
   */
  public static class ColonSeparatedOptionListConverter extends SeparatedOptionListConverter {
    public ColonSeparatedOptionListConverter() {
      super(':', "colon", true);
    }
  }

  /**
   * Converter for colon separated values, where
   * <li>order and multiplicity are assumed to not matter
   * <li>empty values are preserved
   */
  public static class CommaSeparatedOptionSetConverter extends SeparatedOptionSetConverter {
    public CommaSeparatedOptionSetConverter() {
      super(',', "comma", true);
    }
  }

  /** Converter for {@link Level}. */
  public static class LogLevelConverter extends Converter.Contextless<Level> {

    static final ImmutableList<Level> LEVELS =
        ImmutableList.of(
            Level.OFF,
            Level.SEVERE,
            Level.WARNING,
            Level.INFO,
            Level.FINE,
            Level.FINER,
            Level.FINEST);

    @Override
    public Level convert(String input) throws OptionsParsingException {
      try {
        int level = Integer.parseInt(input);
        return LEVELS.get(level);
      } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
        throw new OptionsParsingException("Not a log level: " + input, e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "0 <= an integer <= " + (LEVELS.size() - 1);
    }
  }

  /** Checks whether a string is part of a set of strings. */
  public static class StringSetConverter extends Converter.Contextless<String> {

    // TODO(bazel-team): if this class never actually contains duplicates, we could s/List/Set/
    // here.
    private final ImmutableList<String> values;

    public StringSetConverter(String... values) {
      this.values = ImmutableList.copyOf(values);
    }

    @Override
    public String convert(String input) throws OptionsParsingException {
      if (values.contains(input)) {
        return input;
      }

      throw new OptionsParsingException("Not one of " + values);
    }

    @Override
    public String getTypeDescription() {
      return joinEnglishList(values);
    }
  }

  /** Checks whether a string is a valid regex pattern and compiles it. */
  public static class RegexPatternConverter extends Converter.Contextless<RegexPatternOption> {

    @Override
    public RegexPatternOption convert(String input) throws OptionsParsingException {
      try {
        return RegexPatternOption.create(Pattern.compile(input));
      } catch (PatternSyntaxException e) {
        throw new OptionsParsingException("Not a valid regular expression: " + e.getMessage());
      }
    }

    @Override
    public String getTypeDescription() {
      return "a valid Java regular expression";
    }
  }

  /** Checks whether an integer is in the given range. */
  public static class RangeConverter extends Converter.Contextless<Integer> {
    final int minValue;
    final int maxValue;

    public RangeConverter(int minValue, int maxValue) {
      this.minValue = minValue;
      this.maxValue = maxValue;
    }

    @Override
    public Integer convert(String input) throws OptionsParsingException {
      try {
        int value = Integer.parseInt(input);
        if (value < minValue) {
          throw new OptionsParsingException("'" + input + "' should be >= " + minValue);
        } else if (value < minValue || value > maxValue) {
          throw new OptionsParsingException("'" + input + "' should be <= " + maxValue);
        }
        return value;
      } catch (NumberFormatException e) {
        throw new OptionsParsingException("'" + input + "' is not an int", e);
      }
    }

    @Override
    public String getTypeDescription() {
      if (minValue == Integer.MIN_VALUE) {
        if (maxValue == Integer.MAX_VALUE) {
          return "an integer";
        } else {
          return "an integer, <= " + maxValue;
        }
      } else if (maxValue == Integer.MAX_VALUE) {
        return "an integer, >= " + minValue;
      } else {
        return "an integer in "
            + (minValue < 0 ? "(" + minValue + ")" : minValue)
            + "-"
            + maxValue
            + " range";
      }
    }
  }

  /**
   * A converter for variable assignments from the parameter list of a blaze command invocation.
   * Assignments are expected to have the form "name=value", where names and values are defined to
   * be as permissive as possible.
   */
  public static class AssignmentConverter extends Converter.Contextless<Map.Entry<String, String>> {

    @Override
    public Map.Entry<String, String> convert(String input) throws OptionsParsingException {
      int pos = input.indexOf("=");
      if (pos <= 0) {
        throw new OptionsParsingException(
            "Variable definitions must be in the form of a 'name=value' assignment");
      }
      String name = input.substring(0, pos);
      String value = input.substring(pos + 1);
      return Maps.immutableEntry(name, value);
    }

    @Override
    public String getTypeDescription() {
      return "a 'name=value' assignment";
    }
  }

  /** A converter for for assignments from a string value to a float value. */
  public static class StringToDoubleAssignmentConverter
      extends Converter.Contextless<Map.Entry<String, Double>> {
    private static final AssignmentConverter baseConverter = new AssignmentConverter();

    @Override
    public Map.Entry<String, Double> convert(String input)
        throws OptionsParsingException, NumberFormatException {
      Map.Entry<String, String> stringEntry = baseConverter.convert(input);
      return Maps.immutableEntry(stringEntry.getKey(), Double.parseDouble(stringEntry.getValue()));
    }

    @Override
    public String getTypeDescription() {
      return "a named float, 'name=value'";
    }
  }

  /**
   * A converter for command line flag aliases. It does additional validation on the name and value
   * of the assignment to ensure they conform to the naming limitations.
   */
  public static class FlagAliasConverter extends AssignmentConverter {

    @Override
    public Map.Entry<String, String> convert(String input) throws OptionsParsingException {
      Map.Entry<String, String> entry = super.convert(input);
      String shortForm = entry.getKey();
      String longForm = entry.getValue();

      String cmdLineAlias = "--" + BLAZE_ALIASING_FLAG + "=" + input;

      if (!Pattern.matches("([\\w])*", shortForm)) {
        throw new OptionsParsingException(
            shortForm + " should only consist of word characters to be a valid alias name.",
            cmdLineAlias);
      }
      if (longForm.contains("=")) {
        throw new OptionsParsingException(
            "--" + BLAZE_ALIASING_FLAG + " does not support flag value assignment.", cmdLineAlias);
      }

      // Remove this check if native options are permitted to be aliased
      longForm = "--" + longForm;
      if (STARLARK_SKIPPED_PREFIXES.stream().noneMatch(longForm::startsWith)) {
        throw new OptionsParsingException(
            "--" + BLAZE_ALIASING_FLAG + " only supports Starlark build settings.", cmdLineAlias);
      }

      return entry;
    }

    @Override
    public String getTypeDescription() {
      return "a 'name=value' flag alias";
    }
  }

  /**
   * Base converter for assignments from a value to a list of values. Both the key type as well as
   * the type for all instances in the list of values are processed via passed converters.
   */
  public abstract static class AssignmentToListOfValuesConverter<K, V>
      implements Converter<Map.Entry<K, List<V>>> {

    /** Whether to allow keys in the assignment to be empty (i.e. just a list of values) */
    public enum AllowEmptyKeys {
      YES,
      NO
    }

    private static final Splitter SPLITTER = Splitter.on(',');

    private final Converter<K> keyConverter;
    private final Converter<V> valueConverter;
    private final AllowEmptyKeys allowEmptyKeys;

    public AssignmentToListOfValuesConverter(
        Converter<K> keyConverter, Converter<V> valueConverter, AllowEmptyKeys allowEmptyKeys) {
      this.keyConverter = keyConverter;
      this.valueConverter = valueConverter;
      this.allowEmptyKeys = allowEmptyKeys;
    }

    @Override
    public Map.Entry<K, List<V>> convert(String input, @Nullable Object conversionContext)
        throws OptionsParsingException {
      int pos = input.indexOf("=");
      if (allowEmptyKeys == AllowEmptyKeys.NO && pos <= 0) {
        throw new OptionsParsingException(
            "Must be in the form of a 'key=value[,value]' assignment");
      }

      String key = pos <= 0 ? "" : input.substring(0, pos);
      List<String> values = SPLITTER.splitToList(input.substring(pos + 1));
      if (values.contains("")) {
        // If the list contains exactly the empty string, it means an empty value was passed and we
        // should instead return an empty list.
        if (values.size() == 1) {
          values = ImmutableList.of();
        } else {
          throw new OptionsParsingException(
              "Variable definitions must not contain empty strings or leading / trailing commas");
        }
      }
      ImmutableList.Builder<V> convertedValues = ImmutableList.builder();
      for (String value : values) {
        convertedValues.add(valueConverter.convert(value, conversionContext));
      }
      return Maps.immutableEntry(
          keyConverter.convert(key, conversionContext), convertedValues.build());
    }
  }

  /**
   * A converter for variable assignments from the parameter list of a blaze command invocation.
   * Assignments are expected to have the form {@code [name=]value1[,..,valueN]}, where names and
   * values are defined to be as permissive as possible. If no name is provided, "" is used.
   */
  public static class StringToStringListConverter
      extends AssignmentToListOfValuesConverter<String, String> {

    public StringToStringListConverter() {
      super(new StringConverter(), new StringConverter(), AllowEmptyKeys.YES);
    }

    public Map.Entry<String, List<String>> convert(String input) throws OptionsParsingException {
      return convert(input, /* conversionContext= */ null);
    }

    @Override
    public String getTypeDescription() {
      return "a '[name=]value1[,..,valueN]' assignment";
    }
  }

  /**
   * A converter for variable assignments from the parameter list of a blaze command invocation.
   * Assignments are expected to have the form "name[=value]", where names and values are defined to
   * be as permissive as possible and value part can be optional (in which case it is considered to
   * be null).
   */
  public static class OptionalAssignmentConverter
      extends Converter.Contextless<Map.Entry<String, String>> {

    @Override
    public Map.Entry<String, String> convert(String input) throws OptionsParsingException {
      int pos = input.indexOf('=');
      if (pos == 0 || input.length() == 0) {
        throw new OptionsParsingException(
            "Variable definitions must be in the form of a 'name=value' or 'name' assignment");
      } else if (pos < 0) {
        return Maps.immutableEntry(input, null);
      }
      String name = input.substring(0, pos);
      String value = input.substring(pos + 1);
      return Maps.immutableEntry(name, value);
    }

    @Override
    public boolean starlarkConvertible() {
      return true;
    }

    @Override
    public String reverseForStarlark(Object converted) {
      @SuppressWarnings("unchecked")
      Map.Entry<String, String> typedValue = (Map.Entry<String, String>) converted;
      return typedValue.getValue() == null
          ? typedValue.getKey()
          : String.format("%s=%s", typedValue.getKey(), typedValue.getValue());
    }

    @Override
    public String getTypeDescription() {
      return "a 'name=value' assignment with an optional value part";
    }
  }

  public static class HelpVerbosityConverter extends EnumConverter<OptionsParser.HelpVerbosity> {
    public HelpVerbosityConverter() {
      super(OptionsParser.HelpVerbosity.class, "--help_verbosity setting");
    }
  }

  /**
   * A converter to check whether an integer denoting a percentage is in a valid range: [0, 100].
   */
  public static class PercentageConverter extends RangeConverter {
    public PercentageConverter() {
      super(0, 100);
    }
  }

  /**
   * A {@link Converter} for {@link com.github.benmanes.caffeine.cache.CaffeineSpec}. The spec may
   * be empty, in which case this converter returns null.
   */
  public static final class CaffeineSpecConverter extends Converter.Contextless<CaffeineSpec> {
    @Override
    public CaffeineSpec convert(String spec) throws OptionsParsingException {
      try {
        return CaffeineSpec.parse(spec);
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException("Failed to parse CaffeineSpec: " + e.getMessage(), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "Converts to a CaffeineSpec, or null if the input is empty";
    }
  }
}
