// 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.build.lib.packages;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
import com.google.devtools.build.lib.packages.BuildType.Selector;
import com.google.devtools.build.lib.packages.BuildType.SelectorList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;

/**
 * {@link AttributeMap} implementation that returns raw attribute information as contained within
 * a {@link Rule} via {@link #getRawAttributeValue}. In particular, configurable attributes
 * of the form { config1: "value1", config2: "value2" } are passed through without being resolved
 * to a final value when obtained via that method.
 */
public class RawAttributeMapper extends AbstractAttributeMapper {

  RawAttributeMapper(
      Package pkg, RuleClass ruleClass, Label ruleLabel, AttributeContainer attributes) {
    super(pkg, ruleClass, ruleLabel, attributes);
  }

  public static RawAttributeMapper of(Rule rule) {
    return new RawAttributeMapper(
        rule.getPackage(),
        rule.getRuleClassObject(),
        rule.getLabel(),
        rule.getAttributeContainer());
  }

  /**
   * Variation of {@link #get} that merges the values of configurable lists together (with
   * duplicates removed).
   *
   * <p>For example, given:
   * <pre>
   *   attr = select({
   *       ':condition1': [A, B, C],
   *       ':condition2': [C, D]
   *       }),
   * </pre>
   * this returns the value <code>[A, B, C, D]</code>.
   *
   * <p>If the attribute isn't configurable (e.g. <code>attr = [A, B]</code>), returns
   * its raw value.
   *
   * <p>Throws an {@link IllegalStateException} if the attribute isn't a list type.
   */
  @Nullable
  public <T> Collection<T> getMergedValues(String attributeName, Type<List<T>> type) {
    Preconditions.checkState(type instanceof Type.ListType);
    if (!isConfigurable(attributeName)) {
      return get(attributeName, type);
    }

    ImmutableSet.Builder<T> mergedValues = ImmutableSet.builder();
    for (Selector<List<T>> selector : getSelectorList(attributeName, type).getSelectors()) {
      for (List<T> configuredList : selector.getEntries().values()) {
        mergedValues.addAll(configuredList);
      }
    }
    return mergedValues.build();
  }

  /**
   * If the attribute is configurable for this rule instance, returns its configuration
   * keys. Else returns an empty list.
   */
  public <T> Iterable<Label> getConfigurabilityKeys(String attributeName, Type<T> type) {
    SelectorList<T> selectorList = getSelectorList(attributeName, type);
    if (selectorList == null) {
      return ImmutableList.of();
    }
    ImmutableList.Builder<Label> builder = ImmutableList.builder();
    for (Selector<T> selector : selectorList.getSelectors()) {
      builder.addAll(selector.getEntries().keySet());
    }
    return builder.build();
  }

  /**
   * See {@link #getRawAttributeValue(Rule, Attribute)}.
   *
   * <p>{@param attrName} must be the name of an {@link Attribute} defined by the {@param rule}'s
   * {@link RuleClass}.
   */
  @Nullable
  public Object getRawAttributeValue(Rule rule, String attrName) {
    Attribute attr =
        Preconditions.checkNotNull(getAttributeDefinition(attrName), "%s %s", rule, attrName);
    return getRawAttributeValue(rule, attr);
  }

  /**
   * Returns the object associated with the {@param rule}'s {@param attr}.
   *
   * <p>Handles the special case of the "visibility" attribute by returning {@param rule}'s {@link
   * RuleVisibility}'s declared labels.
   *
   * <p>The returned object will be a {@link SelectorList} if the attribute value contains a
   * {@code select(...)} expression.
   *
   * <p>The returned object will be a {@link ComputedDefault} if the rule doesn't explicitly
   * declare an attribute value and the rule's class provides a computed default for it.
   *
   * <p>Otherwise, the returned object will be the type declared by the {@param attr}, or {@code
   * null}.
   */
  @Nullable
  public Object getRawAttributeValue(Rule rule, Attribute attr) {
    // This special case for the visibility attribute is needed because its value is replaced
    // with an empty list during package loading if it is public or private in order not to visit
    // the package called 'visibility'.
    if (attr.getName().equals("visibility")) {
      return rule.getVisibility().getDeclaredLabels();
    }

    // If the attribute value contains one or more select(...) expressions, then return
    // the SelectorList object representing those expressions.
    SelectorList<?> selectorList = getSelectorList(attr.getName(), attr.getType());
    if (selectorList != null) {
      return selectorList;
    }

    // If the attribute value is not explicitly declared, and the rule class provides a computed
    // default value for it, then we should return the ComputedDefault object.
    //
    // We check for the existence of a ComputedDefault value because AbstractAttributeMapper#get
    // returns either an explicitly declared attribute value or the result of evaluating the
    // computed default function, but does not specify which one it is.
    ComputedDefault computedDefault = getComputedDefault(attr.getName(), attr.getType());
    if (computedDefault != null) {
      return computedDefault;
    }
    return get(attr.getName(), attr.getType());
  }
}
