// 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 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 {

  /** 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 = input.toLowerCase();
      if (input.equals("true")
          || input.equals("1")
          || input.equals("yes")
          || input.equals("t")
          || input.equals("y")) {
        return true;
      }
      if (input.equals("false")
          || input.equals("0")
          || input.equals("no")
          || input.equals("f")
          || input.equals("n")) {
        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");
      }
    }

    @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");
      }
    }

    @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");
      }
    }

    @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 = input.toLowerCase();
      if (input.equals("auto")) {
        return TriState.AUTO;
      }
      if (input.equals("true")
          || input.equals("1")
          || input.equals("yes")
          || input.equals("t")
          || input.equals("y")) {
        return TriState.YES;
      }
      if (input.equals("false")
          || input.equals("0")
          || input.equals("no")
          || input.equals("f")
          || input.equals("n")) {
        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();
  }

  public static class SeparatedOptionListConverter implements Converter<List<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 List<String> convert(String input) throws OptionsParsingException {
      List<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> {

    public static final Level[] LEVELS =
        new Level[] {
          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[level];
      } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
        throw new OptionsParsingException("Not a log level: " + input);
      }
    }

    @Override
    public String getTypeDescription() {
      return "0 <= an integer <= " + (LEVELS.length - 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");
      }
    }

    @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";
    }
  }

  /**
   * 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");
        }
      }
      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");
      }
    }

    @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);
    }
  }
}
