// Copyright 2017 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.actions;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.util.Fingerprint;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * Environment variables for build or test actions.
 *
 * <p>The action environment consists of two parts.
 *
 * <ol>
 *   <li>All the environment variables with a fixed value, stored in a map.
 *   <li>All the environment variables inherited from the client environment, stored in a set.
 * </ol>
 *
 * <p>Inherited environment variables must be declared in the Action interface (see {@link
 * Action#getClientEnvironmentVariables}), so that the dependency on the client environment is known
 * to the execution framework for correct incremental builds.
 *
 * <p>By splitting the environment, we can handle environment variable changes more efficiently -
 * the dependency of the action on the environment variable are tracked in Skyframe (and in the
 * action cache), such that Bazel knows exactly which actions it needs to rerun, and does not have
 * to reanalyze the entire dependency graph.
 */
public final class ActionEnvironment {

  /**
   * A map of environment variables and their values together with a list of variables whose values
   * should be inherited from the client environment.
   */
  public interface EnvironmentVariables {

    /**
     * Returns the fixed environment variables as a map.
     *
     * <p>WARNING: this allocates additional objects if the underlying implementation is a {@link
     * CompoundEnvironmentVariables}; use sparingly.
     */
    ImmutableMap<String, String> getFixedEnvironment();

    /**
     * Returns the inherited environment variables as a set.
     *
     * <p>WARNING: this allocates additional objects if the underlying implementation is a {@link
     * CompoundEnvironmentVariables}; use sparingly.
     */
    ImmutableSet<String> getInheritedEnvironment();

    default boolean isEmpty() {
      return getFixedEnvironment().isEmpty() && getInheritedEnvironment().isEmpty();
    }

    default int size() {
      return getFixedEnvironment().size() + getInheritedEnvironment().size();
    }
  }

  /**
   * An {@link EnvironmentVariables} that combines variables from two different environments without
   * allocating a new map.
   */
  static class CompoundEnvironmentVariables implements EnvironmentVariables {

    static EnvironmentVariables create(
        Map<String, String> fixedVars, Set<String> inheritedVars, EnvironmentVariables base) {
      if (fixedVars.isEmpty() && inheritedVars.isEmpty()) {
        return base;
      }
      return new CompoundEnvironmentVariables(fixedVars, inheritedVars, base);
    }

    private final EnvironmentVariables current;
    private final EnvironmentVariables base;

    private CompoundEnvironmentVariables(
        Map<String, String> fixedVars, Set<String> inheritedVars, EnvironmentVariables base) {
      this.current = SimpleEnvironmentVariables.create(fixedVars, inheritedVars);
      this.base = base;
    }

    @Override
    public boolean isEmpty() {
      return current.isEmpty() && base.isEmpty();
    }

    @Override
    public ImmutableMap<String, String> getFixedEnvironment() {
      LinkedHashMap<String, String> result = new LinkedHashMap<>();
      result.putAll(base.getFixedEnvironment());
      result.putAll(current.getFixedEnvironment());
      return ImmutableMap.copyOf(result);
    }

    @Override
    public ImmutableSet<String> getInheritedEnvironment() {
      ImmutableSet.Builder<String> result = new ImmutableSet.Builder<>();
      result.addAll(base.getInheritedEnvironment());
      result.addAll(current.getInheritedEnvironment());
      return result.build();
    }
  }

  /** A simple {@link EnvironmentVariables}. */
  static class SimpleEnvironmentVariables implements EnvironmentVariables {

    static EnvironmentVariables create(Map<String, String> fixedVars, Set<String> inheritedVars) {
      if (fixedVars.isEmpty() && inheritedVars.isEmpty()) {
        return EMPTY_ENVIRONMENT_VARIABLES;
      }
      return new SimpleEnvironmentVariables(fixedVars, inheritedVars);
    }

    private final ImmutableMap<String, String> fixedVars;
    private final ImmutableSet<String> inheritedVars;

    private SimpleEnvironmentVariables(Map<String, String> fixedVars, Set<String> inheritedVars) {
      this.fixedVars = ImmutableMap.copyOf(fixedVars);
      this.inheritedVars = ImmutableSet.copyOf(inheritedVars);
    }

    @Override
    public ImmutableMap<String, String> getFixedEnvironment() {
      return fixedVars;
    }

    @Override
    public ImmutableSet<String> getInheritedEnvironment() {
      return inheritedVars;
    }
  }

  /** An empty {@link EnvironmentVariables}. */
  public static final EnvironmentVariables EMPTY_ENVIRONMENT_VARIABLES =
      new SimpleEnvironmentVariables(ImmutableMap.of(), ImmutableSet.of());

  /**
   * An empty environment, mainly for testing. Production code should never use this, but instead
   * get the proper environment from the current configuration.
   */
  // TODO(ulfjack): Migrate all production code to use the proper action environment, and then make
  // this @VisibleForTesting or rename it to clarify.
  public static final ActionEnvironment EMPTY = new ActionEnvironment(EMPTY_ENVIRONMENT_VARIABLES);

  /**
   * Splits the given map into a map of variables with a fixed value, and a set of variables that
   * should be inherited, the latter of which are identified by having a {@code null} value in the
   * given map. Returns these two parts as a new {@link ActionEnvironment} instance.
   */
  public static ActionEnvironment split(Map<String, String> env) {
    Map<String, String> fixedEnv = new TreeMap<>();
    Set<String> inheritedEnv = new TreeSet<>();
    for (Map.Entry<String, String> entry : env.entrySet()) {
      if (entry.getValue() != null) {
        fixedEnv.put(entry.getKey(), entry.getValue());
      } else {
        String key = entry.getKey();
        inheritedEnv.add(key);
      }
    }
    return create(SimpleEnvironmentVariables.create(fixedEnv, inheritedEnv));
  }

  private final EnvironmentVariables vars;

  private ActionEnvironment(EnvironmentVariables vars) {
    this.vars = vars;
  }

  /**
   * Creates a new action environment. If an environment variable is contained in both {@link
   * EnvironmentVariables#getFixedEnvironment()} and {@link
   * EnvironmentVariables#getInheritedEnvironment()}, the result of {@link
   * ActionEnvironment#resolve(Map, Map)} will contain the value inherited from the client
   * environment.
   */
  private static ActionEnvironment create(EnvironmentVariables vars) {
    if (vars.isEmpty()) {
      return EMPTY;
    }
    return new ActionEnvironment(vars);
  }

  /**
   * Creates a new action environment. If an environment variable is contained both as a key in
   * {@code fixedEnv} and in {@code inheritedEnv}, the result of {@link
   * ActionEnvironment#resolve(Map, Map)} will contain the value inherited from the client
   * environment.
   */
  public static ActionEnvironment create(
      Map<String, String> fixedEnv, ImmutableSet<String> inheritedEnv) {
    return ActionEnvironment.create(SimpleEnvironmentVariables.create(fixedEnv, inheritedEnv));
  }

  public static ActionEnvironment create(Map<String, String> fixedEnv) {
    return ActionEnvironment.create(SimpleEnvironmentVariables.create(fixedEnv, ImmutableSet.of()));
  }

  /**
   * Returns a copy of the environment with the given fixed variables added to it, <em>overwriting
   * any existing occurrences of those variables</em>.
   */
  public ActionEnvironment withAdditionalFixedVariables(Map<String, String> fixedVars) {
    return withAdditionalVariables(fixedVars, ImmutableSet.of());
  }

  /**
   * Returns a copy of the environment with the given fixed and inherited variables added to it,
   * <em>overwriting any existing occurrences of those variables</em>.
   */
  public ActionEnvironment withAdditionalVariables(
      Map<String, String> fixedVars, Set<String> inheritedVars) {
    EnvironmentVariables newVars =
        CompoundEnvironmentVariables.create(fixedVars, inheritedVars, vars);
    if (newVars == vars) {
      return this;
    }
    return ActionEnvironment.create(newVars);
  }

  /**
   * Returns an upper bound on the combined size of the fixed and inherited environments. A call to
   * {@link ActionEnvironment#resolve(Map, Map)} may add less entries than this number if
   * environment variables are contained in both the fixed and the inherited environment.
   */
  public int size() {
    return vars.size();
  }

  /**
   * Returns the 'fixed' part of the environment, i.e., those environment variables that are set to
   * fixed values and their values. This should only be used for testing and to compute the cache
   * keys of actions. Use {@link #resolve} instead to get the complete environment.
   */
  public ImmutableMap<String, String> getFixedEnv() {
    return vars.getFixedEnvironment();
  }

  /**
   * Returns the 'inherited' part of the environment, i.e., those environment variables that are
   * inherited from the client environment and therefore have no fixed value here. This should only
   * be used for testing and to compute the cache keys of actions. Use {@link #resolve} instead to
   * get the complete environment.
   */
  public ImmutableSet<String> getInheritedEnv() {
    return vars.getInheritedEnvironment();
  }

  /**
   * Resolves the action environment and adds the resulting entries to the given {@code result} map,
   * by looking up any inherited env variables in the given {@code clientEnv}.
   *
   * <p>We pass in a map to mutate to avoid creating and merging intermediate maps.
   */
  public void resolve(Map<String, String> result, Map<String, String> clientEnv) {
    checkNotNull(clientEnv);
    result.putAll(vars.getFixedEnvironment());
    for (String var : vars.getInheritedEnvironment()) {
      String value = clientEnv.get(var);
      if (value != null) {
        result.put(var, value);
      }
    }
  }

  public void addTo(Fingerprint f) {
    f.addStringMap(vars.getFixedEnvironment());
    f.addStrings(vars.getInheritedEnvironment());
  }
}
