// Copyright 2018 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.build.lib.util;

import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Ints;
import com.google.devtools.build.lib.actions.LocalHostCapacity;
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.Map;
import java.util.function.DoubleBinaryOperator;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/**
 * Converter for options that configure Bazel's resource usage.
 *
 * <p>The option can take either a value or one of the keywords {@code auto}, {@code HOST_CPUS}, or
 * {@code HOST_RAM}, followed by an optional operator in the form {@code [-|*]<float>}.
 *
 * <p>If a keyword is passed, the converter returns the keyword's value in the {@link #keywords}
 * map, scaled by the operation that follows if there is one. All values, explicit and derived, are
 * adjusted for validity.
 *
 * <p>The supplier of the auto value, and, optionally, a max or min allowed value (inclusive), are
 * passed to the constructor.
 */
public class ResourceConverter extends Converters.IntegerConverter {

  private static final ImmutableMap<String, DoubleBinaryOperator> OPERATORS =
      ImmutableMap.<String, DoubleBinaryOperator>builder()
          .put("-", (l, r) -> l - r)
          .put("*", (l, r) -> l * r)
          .build();

  /** Description of the accepted inputs to the converter. */
  public static final String FLAG_SYNTAX =
      "an integer, or a keyword (\"auto\", \"HOST_CPUS\", \"HOST_RAM\"), optionally followed by "
          + "an operation ([-|*]<float>) eg. \"auto\", \"HOST_CPUS*.5\"";

  private final ImmutableMap<String, Supplier<Integer>> keywords;

  private final Pattern validInputPattern;

  protected final int minValue;

  protected final int maxValue;

  /**
   * Constructs a ResourceConverter for options that take {@value FLAG_SYNTAX}
   *
   * @param autoSupplier a supplier for the value of the auto keyword
   * @param minValue the minimum allowed value
   * @param maxValue the maximum allowed value
   */
  public ResourceConverter(Supplier<Integer> autoSupplier, int minValue, int maxValue) {
    this(
        ImmutableMap.<String, Supplier<Integer>>builder()
            .put("auto", autoSupplier)
            .put(
                "HOST_CPUS",
                () -> (int) Math.ceil(LocalHostCapacity.getLocalHostCapacity().getCpuUsage()))
            .put(
                "HOST_RAM",
                () -> (int) Math.ceil(LocalHostCapacity.getLocalHostCapacity().getMemoryMb()))
            .build(),
        minValue,
        maxValue);
  }

  /**
   * Constructs a ResourceConverter for options that take {@value FLAG_SYNTAX} and accept any value
   * greater than 1.
   *
   * @param autoSupplier a supplier for the value of the auto keyword
   */
  public ResourceConverter(Supplier<Integer> autoSupplier) {
    this(autoSupplier, 1, Integer.MAX_VALUE);
  }

  /**
   * Constructs a ResourceConverter for options that take keywords other than the default set.
   *
   * @param keywords a map of keyword to the suppliers of their values
   */
  public ResourceConverter(
      ImmutableMap<String, Supplier<Integer>> keywords, int minValue, int maxValue) {
    this.keywords = keywords;
    this.validInputPattern =
        Pattern.compile(
            String.format(
                "(?<keyword>%s)(?<expression>[%s][0-9]?(?:.[0-9]+)?)?",
                String.join("|", this.keywords.keySet()), String.join("", OPERATORS.keySet())));
    this.minValue = minValue;
    this.maxValue = maxValue;
  }

  @Override
  public final Integer convert(String input) throws OptionsParsingException {
    int value;
    if (Ints.tryParse(input) != null) {
      value = super.convert(input);
      return checkAndLimit(value);
    }
    Matcher matcher = validInputPattern.matcher(input);
    if (matcher.matches()) {
      Supplier<Integer> resourceSupplier = keywords.get(matcher.group("keyword"));
      if (resourceSupplier != null) {
        value = applyOperator(matcher.group("expression"), resourceSupplier);
        return checkAndLimit(value);
      }
    }
    throw new OptionsParsingException(
        String.format(
            "Parameter '%s' does not follow correct syntax. This flag takes %s.",
            input, getTypeDescription()));
  }

  /** Applies function designated in {@code expression} ([-|*]<float>) to value. */
  private Integer applyOperator(@Nullable String expression, Supplier<Integer> firstOperandSupplier)
      throws OptionsParsingException {
    if (expression == null) {
      return firstOperandSupplier.get();
    }
    for (Map.Entry<String, DoubleBinaryOperator> operator : OPERATORS.entrySet()) {
      if (expression.startsWith(operator.getKey())) {
        float secondOperand;
        try {
          secondOperand = Float.parseFloat(expression.substring(operator.getKey().length()));
        } catch (NumberFormatException e) {
          throw new OptionsParsingException(
              String.format("'%s is not a float", expression.substring(operator.getKey().length())),
              e);
        }
        return (int)
            Math.round(
                operator
                    .getValue()
                    .applyAsDouble((float) firstOperandSupplier.get(), secondOperand));
      }
    }
    // This should never happen because we've checked for a valid operator already.
    throw new OptionsParsingException(
        String.format("Parameter value '%s' does not contain a valid operator.", expression));
  }

  /**
   * Checks validity of a resource value against min/max constraints. Implementations may choose to
   * either raise an exception on out-of-bounds values, or adjust them to within the constraints.
   */
  public int checkAndLimit(int value) throws OptionsParsingException {
    if (value < minValue) {
      throw new OptionsParsingException(
          String.format("Value '(%d)' must be at least %d.", value, minValue));
    }
    if (value > maxValue) {
      throw new OptionsParsingException(
          String.format("Value '(%d)' cannot be greater than %d.", value, maxValue));
    }
    return value;
  }

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