// Copyright 2017 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.analysis.config;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.FragmentOptions.SelectRestriction;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionMetadataTag;
import com.google.devtools.common.options.OptionsParser;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Maps build option names as they appear to the user (e.g. {@code compilation_mode}) to structured
 * metadata.
 *
 * <p>For native options ({@code @Option} defined in a {@link FragmentOptions} implementation), this
 * tracks:
 *
 * <ul>
 *   <li>what {@link FragmentOptions} class defines the option
 *   <li>the option's current value
 *   <li>whether it allows multiple values to be specified ({@link Option#allowMultiple}
 *   <li>whether it is selectable, i.e., allowed to appear in a {@code config_setting}
 * </ul>
 *
 * <p>For Starlark options (defined in a Starlark {@code build_setting}), this tracks their value in
 * built-in Starlark-object form (post-parse, pre-implementation function form).
 */
public final class BuildOptionDetails {

  /** Builds a {@code BuildOptionDetails} for the given set of native options */
  @VisibleForTesting
  static BuildOptionDetails forOptionsForTesting(
      Iterable<? extends FragmentOptions> buildOptions) {
    return forOptions(buildOptions, ImmutableMap.of());
  }

  /** Builds a {@code BuildOptionDetails} for the given set of native and Starlark options. */
  static BuildOptionDetails forOptions(
      Iterable<? extends FragmentOptions> buildOptions, Map<Label, Object> starlarkOptions) {
    ImmutableMap.Builder<String, OptionDetails> map = ImmutableMap.builder();
    try {
      for (FragmentOptions options : buildOptions) {
        ImmutableList<OptionDefinition> optionDefinitions =
            OptionsParser.getOptionDefinitions(options.getClass());
        Map<OptionDefinition, SelectRestriction> selectRestrictions =
            options.getSelectRestrictions();

        for (OptionDefinition optionDefinition : optionDefinitions) {
          if (ImmutableList.copyOf(optionDefinition.getOptionMetadataTags())
              .contains(OptionMetadataTag.INTERNAL)) {
            // ignore internal options
            continue;
          }
          Object value = optionDefinition.getField().get(options);
          if (value == null && !optionDefinition.isSpecialNullDefault()) {
              // See {@link Option#defaultValue} for an explanation of default "null" strings.
              value = optionDefinition.getUnparsedDefaultValue();
          }
          map.put(
              optionDefinition.getOptionName(),
              new OptionDetails(
                  options.getClass(),
                  value,
                  optionDefinition.allowsMultiple(),
                  selectRestrictions.get(optionDefinition)));
        }
      }
    } catch (IllegalAccessException e) {
      throw new IllegalStateException(
          "Unexpected illegal access trying to create this configuration's options map: ", e);
    }
    return new BuildOptionDetails(map.build(), ImmutableMap.copyOf(starlarkOptions));
  }

  private static final class OptionDetails {

    private OptionDetails(
        Class<? extends FragmentOptions> optionsClass,
        Object value,
        boolean allowsMultiple,
        @Nullable SelectRestriction selectRestriction) {
      this.optionsClass = optionsClass;
      this.value = value;
      this.allowsMultiple = allowsMultiple;
      this.selectRestriction = selectRestriction;
    }

    /** The {@link FragmentOptions} class that defines this option. */
    private final Class<? extends FragmentOptions> optionsClass;

    /** The value of the given option (either explicitly defined or default). May be null. */
    @Nullable private final Object value;

    /** Whether or not this option supports multiple values. */
    private final boolean allowsMultiple;

    /**
     * Information on whether this option is permitted to appear in {@code config_setting}s. Null if
     * there is no such restriction.
     */
    @Nullable private final SelectRestriction selectRestriction;
  }

  /**
   * Maps native option names to the {@link OptionDetails} the option takes for this configuration.
   *
   * <p>This can be used to:
   *
   * <ol>
   *   <li>Find an option's (parsed) value given its command-line name
   *   <li>Parse alternative values for the option.
   * </ol>
   */
  private final ImmutableMap<String, OptionDetails> nativeOptionsMap;

  /** Maps Starlark option labels to values */
  private final ImmutableMap<Label, Object> starlarkOptionsMap;

  private BuildOptionDetails(
      ImmutableMap<String, OptionDetails> nativeOptionsMap,
      ImmutableMap<Label, Object> starlarkOptionsMap) {
    this.nativeOptionsMap = nativeOptionsMap;
    this.starlarkOptionsMap = starlarkOptionsMap;
  }

  /**
   * Returns the {@link FragmentOptions} class the defines the given option, null if the option
   * isn't recognized.
   *
   * <p>optionName is the name of the option as it appears on the command line e.g. {@link
   * OptionDefinition#getOptionName()}).
   */
  @Nullable
  public Class<? extends FragmentOptions> getOptionClass(String optionName) {
    OptionDetails optionDetails = nativeOptionsMap.get(optionName);
    return optionDetails == null ? null : optionDetails.optionsClass;
  }

  /**
   * Returns the value of the specified native option for this configuration or null if the option
   * isn't recognized. Since an option's legitimate value could be null, use {@link #getOptionClass}
   * to distinguish between that and an unknown option.
   *
   * <p>optionName is the name of the option as it appears on the command line e.g. {@link
   * OptionDefinition#getOptionName()}).
   */
  @Nullable
  public Object getOptionValue(String optionName) {
    OptionDetails optionDetails = nativeOptionsMap.get(optionName);
    return (optionDetails == null) ? null : optionDetails.value;
  }

  /** Returns the value of the specified Starlark option or null if it isn't recognized */
  @Nullable
  public Object getOptionValue(Label optionName) {
    return starlarkOptionsMap.get(optionName);
  }

  /**
   * Returns whether or not the given option supports multiple values at the command line (e.g.
   * "--myoption value1 --myOption value2 ..."). Returns false for unrecognized options. Use {@link
   * #getOptionClass} to distinguish between those and legitimate single-value options.
   *
   * <p>As declared in {@link OptionDefinition#allowsMultiple()}, multi-value options are expected
   * to be of type {@code List<T>}.
   */
  public boolean allowsMultipleValues(String optionName) {
    OptionDetails optionDetails = nativeOptionsMap.get(optionName);
    return optionDetails != null && optionDetails.allowsMultiple;
  }

  /**
   * Returns information about whether an option may appear in a {@code config_setting}.
   *
   * <p>Returns null for unrecognized options or options that have no restriction.
   */
  @Nullable
  public SelectRestriction getSelectRestriction(String optionName) {
    OptionDetails optionDetails = nativeOptionsMap.get(optionName);
    return optionDetails == null ? null : optionDetails.selectRestriction;
  }
}
