// 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.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;

/** 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 ImmutableList<String> ENABLED_REPS =
      ImmutableList.of("true", "1", "yes", "t", "y");

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

  /** Standard converter for booleans. Accepts common shorthands/synonyms. */
  public static class BooleanConverter implements Converter<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 implements Converter<String> {
    @Override
    public String convert(String input) {
      return input;
    }

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

  /** Standard converter for integers. */
  public static class IntegerConverter implements Converter<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 implements Converter<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 implements Converter<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 implements Converter<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 implements Converter<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 implements Converter<Duration> {
    private final Pattern durationRegex = 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 = durationRegex.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 implements Converter<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";
    }
  }

  public static class CommaSeparatedOptionListConverter extends SeparatedOptionListConverter {
    public CommaSeparatedOptionListConverter() {
      super(',', "comma", true);
    }
  }

  public static class CommaSeparatedNonEmptyOptionListConverter
      extends SeparatedOptionListConverter {
    public CommaSeparatedNonEmptyOptionListConverter() {
      super(',', "comma", false);
    }
  }

  public static class ColonSeparatedOptionListConverter extends SeparatedOptionListConverter {
    public ColonSeparatedOptionListConverter() {
      super(':', "colon", true);
    }
  }

  public static class LogLevelConverter implements Converter<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 implements Converter<String> {

    // TODO(bazel-team): if this class never actually contains duplicates, we could s/List/Set/
    // here.
    private final List<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 implements Converter<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";
    }
  }

  /** Limits the length of a string argument. */
  public static class LengthLimitingConverter implements Converter<String> {
    private final int maxSize;

    public LengthLimitingConverter(int maxSize) {
      this.maxSize = maxSize;
    }

    @Override
    public String convert(String input) throws OptionsParsingException {
      if (input.length() > maxSize) {
        throw new OptionsParsingException("Input must be " + getTypeDescription());
      }
      return input;
    }

    @Override
    public String getTypeDescription() {
      return "a string <= " + maxSize + " characters";
    }
  }

  /** Checks whether an integer is in the given range. */
  public static class RangeConverter implements Converter<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 {
        Integer 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 implements Converter<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 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) 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));
      }
      return Maps.immutableEntry(keyConverter.convert(key), 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);
    }

    @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 implements Converter<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 String getTypeDescription() {
      return "a 'name=value' assignment with an optional value part";
    }
  }

  /**
   * A converter for named integers of the form "[name=]value". When no name is specified, an empty
   * string is used for the key.
   */
  public static class NamedIntegersConverter implements Converter<Map.Entry<String, Integer>> {

    @Override
    public Map.Entry<String, Integer> convert(String input) throws OptionsParsingException {
      int pos = input.indexOf('=');
      if (pos == 0 || input.length() == 0) {
        throw new OptionsParsingException(
            "Specify either 'value' or 'name=value', where 'value' is an integer");
      } else if (pos < 0) {
        try {
          return Maps.immutableEntry("", Integer.parseInt(input));
        } catch (NumberFormatException e) {
          throw new OptionsParsingException("'" + input + "' is not an int", e);
        }
      }
      String name = input.substring(0, pos);
      String value = input.substring(pos + 1);
      try {
        return Maps.immutableEntry(name, Integer.parseInt(value));
      } catch (NumberFormatException e) {
        throw new OptionsParsingException("'" + value + "' is not an int", e);
      }
    }

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

  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 implements Converter<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";
    }
  }
}
