// Copyright 2015 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.Predicate;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.starlark.java.syntax.Location;

/**
 * Model for the "environment_group' rule: the piece of Bazel's rule constraint system that binds
 * thematically related environments together and determines which environments a rule supports by
 * default. See {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for
 * precise semantic details of how this information is used.
 *
 * <p>Note that "environment_group" is implemented as a loading-time function, not a rule. This is
 * to support proper discovery of defaults: Say rule A has no explicit constraints and depends on
 * rule B, which is explicitly constrained to environment ":bar". Since A declares nothing
 * explicitly, it's implicitly constrained to DEFAULTS (whatever that is). Therefore, the dependency
 * is only allowed if DEFAULTS doesn't include environments beyond ":bar". To figure that out, we
 * need to be able to look up the environment group for ":bar", which is what this class provides.
 *
 * <p>If we implemented this as a rule, we'd have to provide that lookup via rule dependencies, e.g.
 * something like: <code>
 *   environment(
 *       name = 'bar',
 *       group = [':sample_environments'],
 *       is_default = 1
 *   )
 * </code>
 *
 * <p>But this won't work. This would let us find the environment group for ":bar", but the only way
 * to determine what other environments belong to the group is to have the group somehow reference
 * them. That would produce circular dependencies in the build graph, which is no good.
 */
@Immutable // This is a lie, but this object is only mutable until its containing package is loaded.
public class EnvironmentGroup implements Target {
  private final EnvironmentLabels environmentLabels;
  private final Location location;
  private final Package containingPackage;

  /**
   * Predicate that matches labels from a different package than the initialized package.
   */
  private static final class DifferentPackage implements Predicate<Label> {
    private final Package containingPackage;

    private DifferentPackage(Package containingPackage) {
      this.containingPackage = containingPackage;
    }

    @Override
    public boolean apply(Label environment) {
      return !environment.getPackageName().equals(containingPackage.getName());
    }
  }

  /**
   * Instantiates a new group without verifying the soundness of its contents. See the validation
   * methods below for appropriate checks.
   *
   * @param label the build label identifying this group
   * @param pkg the package this group belongs to
   * @param environments the set of environments that belong to this group
   * @param defaults the environments a rule implicitly supports unless otherwise specified
   * @param location location in the BUILD file of this group
   */
  EnvironmentGroup(
      Label label,
      Package pkg,
      final List<Label> environments,
      List<Label> defaults,
      Location location) {
    this.environmentLabels = new EnvironmentLabels(label, environments, defaults);
    this.location = location;
    this.containingPackage = pkg;
  }

  @Override
  public boolean isImmutable() {
    return true; // immutable and Starlark-hashable
  }

  public EnvironmentLabels getEnvironmentLabels() {
    environmentLabels.checkInitialized();
    return environmentLabels;
  }

  /**
   * Checks that all environments declared by this group are in the same package as the group (so
   * we can perform an environment --> environment_group lookup and know the package is available)
   * and checks that all defaults are legitimate members of the group.
   *
   * <p>Does <b>not</b> check that the referenced environments exist (see
   * {@link #processMemberEnvironments}).
   *
   * @return a list of validation errors that occurred
   */
  List<Event> validateMembership() {
    List<Event> events = new ArrayList<>();

    // All environments should belong to the same package as this group.
    for (Label environment :
        Iterables.filter(environmentLabels.environments, new DifferentPackage(containingPackage))) {
      events.add(
          Package.error(
              location,
              environment + " is not in the same package as group " + environmentLabels.label,
              Code.ENVIRONMENT_IN_DIFFERENT_PACKAGE));
    }

    // The defaults must be a subset of the member environments.
    for (Label unknownDefault :
        Sets.difference(environmentLabels.defaults, environmentLabels.environments)) {
      events.add(
          Package.error(
              location,
              String.format(
                  "default %s is not a declared environment for group %s",
                  unknownDefault, getLabel()),
              Code.DEFAULT_ENVIRONMENT_UNDECLARED));
    }

    return events;
  }

  /**
   * Checks that the group's declared environments are legitimate same-package environment rules and
   * prepares the "fulfills" relationships between these environments to support {@link
   * EnvironmentLabels#getFulfillers}.
   *
   * @param pkgTargets mapping from label name to target instance for this group's package
   * @return a list of validation errors that occurred
   */
  List<Event> processMemberEnvironments(Map<String, Target> pkgTargets) {
    List<Event> events = new ArrayList<>();
    // Maps an environment to the environments that directly fulfill it.
    Multimap<Label, Label> directFulfillers = HashMultimap.create();

    for (Label envName : environmentLabels.environments) {
      Target env = pkgTargets.get(envName.getName());
      if (isValidEnvironment(env, envName, "", events)) {
        AttributeMap attr = NonconfigurableAttributeMapper.of((Rule) env);
        for (Label fulfilledEnv : attr.get("fulfills", BuildType.LABEL_LIST)) {
          if (isValidEnvironment(pkgTargets.get(fulfilledEnv.getName()), fulfilledEnv,
              "in \"fulfills\" attribute of " + envName + ": ", events)) {
            directFulfillers.put(fulfilledEnv, envName);
          }
        }
      }
    }

    Map<Label, NestedSet<Label>> fulfillersMap = new HashMap<>();
    // Now that we know which environments directly fulfill each other, compute which environments
    // transitively fulfill each other. We could alternatively compute this on-demand, but since
    // we don't expect these chains to be very large we opt toward computing them once at package
    // load time.
    environmentLabels.assertNotInitialized();
    for (Label envName : environmentLabels.environments) {
      setTransitiveFulfillers(envName, directFulfillers, fulfillersMap);
    }

    environmentLabels.setFulfillersMap(fulfillersMap);
    return events;
  }

  /**
   * Given an environment and set of environments that directly fulfill it, computes a nested
   * set of environments that <i>transitively</i> fulfill it, places it into transitiveFulfillers,
   * and returns that set.
   */
  private static NestedSet<Label> setTransitiveFulfillers(Label env,
      Multimap<Label, Label> directFulfillers, Map<Label, NestedSet<Label>> transitiveFulfillers) {
    if (transitiveFulfillers.containsKey(env)) {
      return transitiveFulfillers.get(env);
    } else if (!directFulfillers.containsKey(env)) {
      // Nobody fulfills this environment.
      NestedSet<Label> emptySet = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
      transitiveFulfillers.put(env, emptySet);
      return emptySet;
    } else {
      NestedSetBuilder<Label> set = NestedSetBuilder.stableOrder();
      for (Label fulfillingEnv : directFulfillers.get(env)) {
        set.add(fulfillingEnv);
        set.addTransitive(
            setTransitiveFulfillers(fulfillingEnv, directFulfillers, transitiveFulfillers));
      }
      NestedSet<Label> builtSet = set.build();
      transitiveFulfillers.put(env, builtSet);
      return builtSet;
    }
  }

  private boolean isValidEnvironment(Target env, Label envName, String prefix, List<Event> events) {
    if (env == null) {
      events.add(
          Package.error(
              location,
              prefix + "environment " + envName + " does not exist",
              Code.ENVIRONMENT_DOES_NOT_EXIST));
      return false;
    } else if (!env.getTargetKind().equals("environment rule")) {
      events.add(
          Package.error(
              location,
              prefix + env.getLabel() + " is not a valid environment",
              Code.ENVIRONMENT_INVALID));
      return false;
    } else if (!environmentLabels.environments.contains(env.getLabel())) {
      events.add(
          Package.error(
              location,
              prefix + env.getLabel() + " is not a member of this group",
              Code.ENVIRONMENT_NOT_IN_GROUP));
      return false;
    }
    return true;
  }

  /**
   * Returns the environments that belong to this group.
   */
  public Set<Label> getEnvironments() {
    return environmentLabels.environments;
  }

  /**
   * Returns the environments a rule supports by default, i.e. if it has no explicit references to
   * environments in this group.
   */
  public Set<Label> getDefaults() {
    return environmentLabels.defaults;
  }

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

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

  @Override
  public Package getPackage() {
    return containingPackage;
  }

  @Override
  public String getTargetKind() {
    return targetKind();
  }

  @Override
  public Rule getAssociatedRule() {
    return null;
  }

  @Override
  public License getLicense() {
    return License.NO_LICENSE;
  }

  @Override
  public Location getLocation() {
    return location;
  }

  @Override
  public String toString() {
    return targetKind() + " " + getLabel();
  }

  @Override
  public Set<License.DistributionType> getDistributions() {
    return Collections.emptySet();
  }

  @Override
  public RuleVisibility getVisibility() {
    return ConstantRuleVisibility.PRIVATE; // No rule should be referencing an environment_group.
  }

  @Override
  public boolean isConfigurable() {
    return false;
  }

  public static String targetKind() {
    return "environment group";
  }
}
