// Copyright 2016 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;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.Type;
import java.util.Collection;

/**
 * An {@link AttributeMap} that supports attribute type queries on both a rule and its aspects and
 * attribute value queries on the rule.
 *
 * <p>An attribute type query is anything accessible from {@link Attribute} (i.e. anything about how
 * the attribute is integrated into the {@link RuleClass}). An attribute value query is anything
 * related to the actual value an attribute takes.
 *
 * <p>For example, given {@code deps = [":adep"]}, checking that {@code deps} exists or that it's
 * type is {@link com.google.devtools.build.lib.packages.BuildType#LABEL_LIST} are type queries.
 * Checking that its value is explicitly set in the BUILD File or that its value {@code [":adep"]}
 * are value queries..
 *
 * <p>Value queries on aspect attributes trigger {@link UnsupportedOperationException}.
 */
class AspectAwareAttributeMapper implements AttributeMap {
  private final AttributeMap ruleAttributes;
  private final ImmutableMap<String, Attribute> aspectAttributes;

  public AspectAwareAttributeMapper(AttributeMap ruleAttributes,
      ImmutableMap<String, Attribute> aspectAttributes) {
    this.ruleAttributes = ruleAttributes;
    this.aspectAttributes = aspectAttributes;
  }

  /**
   * Don't use this except where absolutely necessary. This exposes internal implementation details.
   */
  ImmutableMap<String, Attribute> getAspectAttributes() {
    return aspectAttributes;
  }

  @Override
  public String getName() {
    return ruleAttributes.getName();
  }

  @Override
  public String getRuleClassName() {
    return ruleAttributes.getRuleClassName();
  }

  @Override
  public Label getLabel() {
    return ruleAttributes.getLabel();
  }

  @Override
  public <T> T get(String attributeName, Type<T> type) {
    if (ruleAttributes.has(attributeName, type)) {
      return ruleAttributes.get(attributeName, type);
    } else {
      Attribute attribute = aspectAttributes.get(attributeName);
      if (attribute == null) {
        throw new IllegalArgumentException(String.format(
            "no attribute '%s' in either %s or its aspects",
            attributeName, ruleAttributes.getLabel()));
      } else if (attribute.getType() != type) {
        throw new IllegalArgumentException(String.format(
            "attribute %s has type %s, not expected type %s",
            attributeName, attribute.getType(), type));
      } else {
        throw new UnsupportedOperationException(
            String.format(
                "Attribute '%s' comes from an aspect. "
                    + "Value retrieval for aspect attributes is not supported.",
                attributeName));
      }
    }
  }

  @Override
  public boolean isConfigurable(String attributeName) {
    return ruleAttributes.isConfigurable(attributeName);
  }

  @Override
  public Iterable<String> getAttributeNames() {
    return ImmutableList.<String>builder()
        .addAll(ruleAttributes.getAttributeNames())
        .addAll(aspectAttributes.keySet())
        .build();
  }

  @Override
  public Type<?> getAttributeType(String attrName) {
    Type<?> type = ruleAttributes.getAttributeType(attrName);
    if (type != null) {
      return type;
    } else {
      Attribute attribute = aspectAttributes.get(attrName);
      return attribute != null ? attribute.getType() : null;
    }
  }

  @Override
  public Attribute getAttributeDefinition(String attrName) {
    Attribute attribute = ruleAttributes.getAttributeDefinition(attrName);
    if (attribute != null) {
      return attribute;
    } else {
      return aspectAttributes.get(attrName);
    }
  }

  @Override
  public boolean isAttributeValueExplicitlySpecified(String attributeName) {
    return ruleAttributes.isAttributeValueExplicitlySpecified(attributeName);
  }

  @Override
  public Collection<DepEdge> visitLabels() throws InterruptedException {
    throw new UnsupportedOperationException("rule + aspects label visition is not supported");
  }

  @Override
  public Collection<DepEdge> visitLabels(Attribute attribute) throws InterruptedException {
    throw new UnsupportedOperationException("rule + aspects label visition is not supported");
  }

  @Override
  public String getPackageDefaultHdrsCheck() {
    return ruleAttributes.getPackageDefaultHdrsCheck();
  }

  @Override
  public Boolean getPackageDefaultTestOnly() {
    return ruleAttributes.getPackageDefaultTestOnly();
  }

  @Override
  public String getPackageDefaultDeprecation() {
    return ruleAttributes.getPackageDefaultDeprecation();
  }

  @Override
  public ImmutableList<String> getPackageDefaultCopts() {
    return ruleAttributes.getPackageDefaultCopts();
  }

  @Override
  public boolean has(String attrName) {
    if (ruleAttributes.has(attrName)) {
      return true;
    } else {
      return aspectAttributes.containsKey(attrName);
    }
  }

  @Override
  public <T> boolean has(String attrName, Type<T> type) {
    if (ruleAttributes.has(attrName, type)) {
      return true;
    } else {
      return aspectAttributes.containsKey(attrName)
          && aspectAttributes.get(attrName).getType() == type;
    }
  }
}
