// 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 com.google.devtools.build.lib.syntax.Type;
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());
  }
}
