// Copyright 2019 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.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.util.FileTypeSet;
import javax.annotation.Nullable;

/**
 * Helper functions for visiting the {@link Label}s of the loading-phase deps of a {@link Target}
 * that are entailed by the values of the {@link Target}'s attributes. Notably, this does *not*
 * include aspect-entailed deps.
 */
public final class LabelVisitationUtils {

  // An attribute which symbolizes the "toolchains" parameter of rule class definitions
  // (user-specified via the `toolchains` parameter of the starlark rule() function). This is so
  // that labels specified in this `toolchains` parameter may be treated the same as dependencies
  // defined on an implicit rule attribute. This "fake" attribute uses an obscure placeholder name
  // to prevent dependencies on this implementation detail.
  private static final Attribute TOOLCHAIN_TYPE_ATTR_FOR_FILTERING =
      Attribute.attr("_hidden_toolchain_types", BuildType.LABEL_LIST)
          .allowedFileTypes(FileTypeSet.NO_FILE)
          .build();

  private LabelVisitationUtils() {}

  /** Interface for processing the {@link Label} of dep, one at a time. */
  public interface LabelProcessor {
    /**
     * Processes the {@link Label} of a single dep.
     *
     * @param from the {@link Target} that has the dep.
     * @param attribute if non-{@code null}, the {@link Attribute} whose value entailed the dep.
     * @param to the {@link Label} of the dep.
     */
    void process(Target from, @Nullable Attribute attribute, Label to);
  }

  /**
   * Visits the loading-phase deps of {@code target} that satisfy {@code edgeFilter}, feeding each
   * one to {@code labelProcessor} in a streaming manner.
   */
  public static void visitTarget(
      Target target, DependencyFilter edgeFilter, LabelProcessor labelProcessor) {
    if (target instanceof OutputFile) {
      labelProcessor.process(
          target, /*attribute=*/ null, ((OutputFile) target).getGeneratingRule().getLabel());
      visitTargetVisibility(target, /*attribute=*/ null, labelProcessor);
      return;
    }

    if (target instanceof InputFile) {
      visitTargetVisibility(target, /*attribute=*/ null, labelProcessor);
      return;
    }

    if (target instanceof Rule) {
      Rule rule = (Rule) target;
      visitRuleVisibility(rule, edgeFilter, labelProcessor);
      visitRule(rule, edgeFilter, labelProcessor);
      visitRuleToolchains(rule, edgeFilter, labelProcessor);
      return;
    }

    if (target instanceof PackageGroup) {
      visitPackageGroup((PackageGroup) target, labelProcessor);
    }
  }

  private static void visitTargetVisibility(
      Target target, @Nullable Attribute attribute, LabelProcessor labelProcessor) {
    for (Label label : target.getVisibilityDependencyLabels()) {
      labelProcessor.process(target, attribute, label);
    }
  }

  private static void visitRuleVisibility(
      Rule rule, DependencyFilter edgeFilter, LabelProcessor labelProcessor) {
    RuleClass ruleClass = rule.getRuleClassObject();
    Integer index = ruleClass.getAttributeIndex("visibility");
    if (index == null) {
      return;
    }
    Attribute visibilityAttribute = ruleClass.getAttribute(index);
    if (visibilityAttribute.getType() != BuildType.NODEP_LABEL_LIST) {
      return;
    }
    if (edgeFilter.test(rule, visibilityAttribute)) {
      visitTargetVisibility(rule, visibilityAttribute, labelProcessor);
    }
  }

  private static void visitRuleToolchains(
      Rule rule, DependencyFilter edgeFilter, LabelProcessor labelProcessor) {
    RuleClass ruleClass = rule.getRuleClassObject();
    if (edgeFilter.test(rule, TOOLCHAIN_TYPE_ATTR_FOR_FILTERING)) {
      for (ToolchainTypeRequirement t : ruleClass.getToolchainTypes()) {
        labelProcessor.process(rule, TOOLCHAIN_TYPE_ATTR_FOR_FILTERING, t.toolchainType());
      }
    }
  }

  private static void visitRule(
      Rule rule, DependencyFilter edgeFilter, LabelProcessor labelProcessor) {
    AggregatingAttributeMapper.of(rule)
        .visitLabels(
            edgeFilter,
            (Label label, Attribute attribute) -> {
              if (label == null) {
                return;
              }
              labelProcessor.process(rule, attribute, label);
            });
  }

  private static void visitPackageGroup(PackageGroup packageGroup, LabelProcessor labelProcessor) {
    for (Label label : packageGroup.getIncludes()) {
      labelProcessor.process(packageGroup, /*attribute=*/ null, label);
    }
  }
}
