// 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.buildOrThrow(), 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;
  }
}
