// 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.rules.proto;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;

/**
 * A blacklist of proto source files.
 *
 * <p>There are cases where we need to identify proto files that we should not create generated
 * files for. For example, we should not create generated code for google/protobuf/any.proto, which
 * is already baked into the language support libraries. This class provides us with the ability
 * to identify these proto files and avoid linking in their associated generated files.
 */
public class ProtoSourceFileBlacklist {
  private static final PathFragment BAZEL_TOOLS_PREFIX =
      PathFragment.create("external/bazel_tools/");
  private final RuleContext ruleContext;
  private final ImmutableSet<PathFragment> blacklistProtoFilePaths;

  /**
   * Creates a proto source file blacklist.
   *
   * @param ruleContext the proto rule context.
   * @param blacklistProtoFiles a list of blacklisted .proto files. The list will be iterated.
   *     protos.
   */
  public ProtoSourceFileBlacklist(RuleContext ruleContext, Iterable<Artifact> blacklistProtoFiles) {
    this.ruleContext = ruleContext;
    ImmutableSet.Builder<PathFragment> blacklistProtoFilePathsBuilder =
        new ImmutableSet.Builder<>();
    for (Artifact blacklistProtoFile : blacklistProtoFiles) {
      PathFragment execPath = blacklistProtoFile.getExecPath();
      // For blacklisted protos bundled with the Bazel tools repository, their exec paths start
      // with external/bazel_tools/. This prefix needs to be removed first, because the protos in
      // user repositories will not have that prefix.
      if (execPath.startsWith(BAZEL_TOOLS_PREFIX)) {
        blacklistProtoFilePathsBuilder.add(execPath.relativeTo(BAZEL_TOOLS_PREFIX));
      } else {
        blacklistProtoFilePathsBuilder.add(execPath);
      }
    }
    blacklistProtoFilePaths = blacklistProtoFilePathsBuilder.build();
  }

  /**
   * Filters the blacklisted protos from the given protos.
   */
  public Iterable<Artifact> filter(Iterable<Artifact> protoFiles) {
    return Streams.stream(protoFiles).filter(f -> !isBlacklisted(f)).collect(toImmutableSet());
  }

  /**
   * Checks the proto sources for mixing blacklisted and non-blacklisted protos in one single
   * proto_library rule. Registers an attribute error if proto mixing is detected.
   *
   * @param protoFiles the protos to filter.
   * @param topLevelProtoRuleName the name of the top-level rule that generates the protos.
   * @return whether the proto sources are clean without mixing.
   */
  public boolean checkSrcs(Iterable<Artifact> protoFiles, String topLevelProtoRuleName) {
    List<Artifact> blacklisted = new ArrayList<>();
    List<Artifact> nonBlacklisted = new ArrayList<>();
    for (Artifact protoFile : protoFiles) {
      if (isBlacklisted(protoFile)) {
        blacklisted.add(protoFile);
      } else {
        nonBlacklisted.add(protoFile);
      }
    }
    if (!nonBlacklisted.isEmpty() && !blacklisted.isEmpty()) {
      ruleContext.attributeError(
          "srcs",
          createBlacklistedProtosMixError(
              Artifact.toRootRelativePaths(blacklisted),
              Artifact.toRootRelativePaths(nonBlacklisted),
              ruleContext.getLabel().toString(),
              topLevelProtoRuleName));
    }

    return blacklisted.isEmpty();
  }

  /**
   * Returns whether the given proto file is blacklisted.
   */
  public boolean isBlacklisted(Artifact protoFile) {
    return blacklistProtoFilePaths.contains(protoFile.getExecPath());
  }

  /**
   * Returns an attribute for the implicit dependency on blacklist proto filegroups.
   * @param attributeName the name of the attribute.
   * @param blacklistFileGroups a list of labels pointin to the filegroups containing blacklisted
   *     protos.
   */
  public static Attribute.Builder<List<Label>> blacklistFilegroupAttribute(
      String attributeName, List<Label> blacklistFileGroups) {
    return attr(attributeName, LABEL_LIST)
        .cfg(HostTransition.createFactory())
        .value(blacklistFileGroups);
  }

  @VisibleForTesting
  public static String createBlacklistedProtosMixError(
      Iterable<String> blacklisted, Iterable<String> nonBlacklisted, String protoLibraryRuleLabel,
      String topLevelProtoRuleName) {
    return String.format(
        "The 'srcs' attribute of '%s' contains protos for which '%s' "
            + "shouldn't generate code (%s), in addition to protos for which it should (%s).\n"
            + "Separate '%1$s' into 2 proto_library rules.",
        protoLibraryRuleLabel,
        topLevelProtoRuleName,
        Joiner.on(", ").join(blacklisted),
        Joiner.on(", ").join(nonBlacklisted));
  }
}
