// 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.syntax;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.syntax.Mutability.MutabilityException;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A {@link Module} represents a Starlark module, a container of global variables populated by
 * executing a Starlark file. Each top-level assignment updates a global variable in the module.
 *
 * <p>Each module references its "predeclared" environment, which is often shared among many
 * modules. These are the names that are defined even at the start of execution. For example, in
 * Bazel, the predeclared environment of the module for a BUILD or .bzl file defines name values
 * such as cc_binary and glob.
 *
 * <p>The predeclared environment currently must include the "universal" names present in every
 * Starlark thread in every dialect, such as None, len, and str.
 *
 * <p>Global bindings in a Module may shadow bindings inherited from the predeclared or universe
 * block.
 *
 * <p>A module may carry an arbitrary piece of metadata called its "label". In Bazel, for example,
 * the label is a build label such as "//dir:file.bzl", for use by the Label function. This is a
 * hack.
 *
 * <p>A {@link Module} may be constructed in a two-phase process. To do this, call the nullary
 * constructor to create an uninitialized {@link Module}, then call {@link #initialize}. It is
 * illegal to use any other method in-between these two calls, or to call {@link #initialize} on an
 * already initialized {@link Module}.
 */
// TODO(adonovan):
// - make fields private where possible.
// - remove references to this from StarlarkThread.
// - separate the universal predeclared environment and make it implicit.
// - eliminate initialize(). The only constructor we need is:
//   (String name, Mutability mu, Map<String, Object> predeclared, Object label).
public final class Module implements ValidationEnvironment.Module {

  /**
   * Final, except that it may be initialized after instantiation. Null mutability indicates that
   * this Frame is uninitialized.
   */
  @Nullable private Mutability mutability;

  /** Final, except that it may be initialized after instantiation. */
  @Nullable Module universe;

  // The label (an optional piece of metadata) associated with the file.
  @Nullable Object label;

  /** Bindings are maintained in order of creation. */
  private final LinkedHashMap<String, Object> bindings;

  /**
   * A list of bindings which *would* exist in this global frame under certain semantic flags, but
   * do not exist using the semantic flags used in this frame's creation. This map should not be
   * used for lookups; it should only be used to throw descriptive error messages when a lookup of a
   * restricted object is attempted.
   */
  final LinkedHashMap<String, FlagGuardedValue> restrictedBindings;

  /** Set of bindings that are exported (can be loaded from other modules). */
  final HashSet<String> exportedBindings;

  /** Constructs an uninitialized instance; caller must call {@link #initialize} before use. */
  public Module() {
    this.mutability = null;
    this.universe = null;
    this.label = null;
    this.bindings = new LinkedHashMap<>();
    this.restrictedBindings = new LinkedHashMap<>();
    this.exportedBindings = new HashSet<>();
  }

  /**
   * Returns the module (file) of the innermost enclosing Starlark function on the call stack, or
   * null if none of the active calls are functions defined in Starlark.
   *
   * <p>The name of this function is intentionally horrible to make you feel bad for using it.
   */
  @Nullable
  public static Module ofInnermostEnclosingStarlarkFunction(StarlarkThread thread) {
    for (Debug.Frame fr : thread.getDebugCallStack().reverse()) {
      if (fr.getFunction() instanceof StarlarkFunction) {
        return ((StarlarkFunction) fr.getFunction()).getModule();
      }
    }
    return null;
  }

  Module(
      Mutability mutability,
      @Nullable Module universe,
      @Nullable Object label,
      @Nullable Map<String, Object> bindings,
      @Nullable Map<String, FlagGuardedValue> restrictedBindings) {
    Preconditions.checkState(universe == null || universe.universe == null);
    this.mutability = Preconditions.checkNotNull(mutability);
    this.universe = universe;
    if (label != null) {
      this.label = label;
    } else if (universe != null) {
      this.label = universe.label;
    } else {
      this.label = null;
    }
    this.bindings = new LinkedHashMap<>();
    if (bindings != null) {
      this.bindings.putAll(bindings);
    }
    this.restrictedBindings = new LinkedHashMap<>();
    if (restrictedBindings != null) {
      this.restrictedBindings.putAll(restrictedBindings);
    }
    if (universe != null) {
      this.restrictedBindings.putAll(universe.restrictedBindings);
    }
    this.exportedBindings = new HashSet<>();
  }

  public Module(Mutability mutability) {
    this(mutability, null, null, null, null);
  }

  public Module(Mutability mutability, @Nullable Module universe) {
    this(mutability, universe, null, null, null);
  }

  public Module(Mutability mutability, @Nullable Module universe, @Nullable Object label) {
    this(mutability, universe, label, null, null);
  }

  /** Constructs a global frame for the given builtin bindings. */
  public static Module createForBuiltins(Map<String, Object> bindings) {
    Mutability mutability = Mutability.create("<builtins>").freeze();
    return new Module(mutability, null, null, bindings, null);
  }

  /**
   * Constructs a global frame based on the given parent frame, filtering out flag-restricted global
   * objects.
   */
  static Module filterOutRestrictedBindings(
      Mutability mutability, Module parent, StarlarkSemantics semantics) {
    if (parent == null) {
      return new Module(mutability);
    }
    Preconditions.checkArgument(parent.mutability().isFrozen(), "parent frame must be frozen");
    Preconditions.checkArgument(parent.universe == null);

    Map<String, Object> filteredBindings = new LinkedHashMap<>();
    Map<String, FlagGuardedValue> restrictedBindings = new LinkedHashMap<>();

    for (Map.Entry<String, Object> binding : parent.bindings.entrySet()) {
      if (binding.getValue() instanceof FlagGuardedValue) {
        FlagGuardedValue val = (FlagGuardedValue) binding.getValue();
        if (val.isObjectAccessibleUsingSemantics(semantics)) {
          filteredBindings.put(binding.getKey(), val.getObject());
        } else {
          restrictedBindings.put(binding.getKey(), val);
        }
      } else {
        filteredBindings.put(binding.getKey(), binding.getValue());
      }
    }

    restrictedBindings.putAll(parent.restrictedBindings);

    return new Module(
        mutability, /*universe=*/ null, parent.label, filteredBindings, restrictedBindings);
  }

  private void checkInitialized() {
    Preconditions.checkNotNull(mutability, "Attempted to use Frame before initializing it");
  }

  public void initialize(
      Mutability mutability,
      @Nullable Module universe,
      @Nullable Object label,
      Map<String, Object> bindings) {
    Preconditions.checkState(
        universe == null || universe.universe == null); // no more than 1 universe
    Preconditions.checkState(
        this.mutability == null, "Attempted to initialize an already initialized Frame");
    this.mutability = Preconditions.checkNotNull(mutability);
    this.universe = universe;
    if (label != null) {
      this.label = label;
    } else if (universe != null) {
      this.label = universe.label;
    } else {
      this.label = null;
    }
    this.bindings.putAll(bindings);
  }

  /**
   * Returns a new {@link Module} with the same fields, except that {@link #label} is set to the
   * given value. The label associated with each function (frame) on the stack is accessible using
   * {@link #getLabel}, and is included in the result of {@code str(fn)} where {@code fn} is a
   * StarlarkFunction.
   */
  public Module withLabel(Object label) {
    checkInitialized();
    return new Module(
        mutability, /*universe=*/ null, label, bindings, /*restrictedBindings=*/ null);
  }

  /** Returns the {@link Mutability} of this {@link Module}. */
  public Mutability mutability() {
    checkInitialized();
    return mutability;
  }

  /**
   * Returns the parent {@link Module}, if it exists.
   *
   * <p>TODO(laurentlb): Should be called getUniverse.
   */
  @Nullable
  public Module getParent() {
    checkInitialized();
    return universe;
  }

  /**
   * Returns the label (an optional piece of metadata) associated with this {@code Module}. (For
   * Bazel LOADING threads, this is the build label of its BUILD or .bzl file.)
   */
  @Nullable
  public Object getLabel() {
    checkInitialized();
    return label;
  }

  /**
   * Returns a map of direct bindings of this {@link Module}, ignoring universe.
   *
   * <p>The bindings are returned in a deterministic order (for a given sequence of initial values
   * and updates).
   *
   * <p>For efficiency an unmodifiable view is returned. Callers should assume that the view is
   * invalidated by any subsequent modification to the {@link Module}'s bindings.
   */
  public Map<String, Object> getBindings() {
    checkInitialized();
    return Collections.unmodifiableMap(bindings);
  }

  /**
   * Returns a map of bindings that are exported (i.e. symbols declared using `=` and `def`, but not
   * `load`).
   */
  // TODO(adonovan): whether bindings are exported should be decided by the resolver;
  // non-exported bindings should never be added to the module.
  public Map<String, Object> getExportedBindings() {
    checkInitialized();
    ImmutableMap.Builder<String, Object> result = new ImmutableMap.Builder<>();
    for (Map.Entry<String, Object> entry : bindings.entrySet()) {
      if (exportedBindings.contains(entry.getKey())) {
        result.put(entry);
      }
    }
    return result.build();
  }

  @Override
  public Set<String> getNames() {
    return getTransitiveBindings().keySet();
  }

  @Override
  public String getUndeclaredNameError(String name) {
    FlagGuardedValue v = restrictedBindings.get(name);
    return v == null ? null : v.getErrorFromAttemptingAccess(name);
  }

  /** Returns an environment containing both module and predeclared bindings. */
  // TODO(adonovan): eliminate in favor of explicit module vs. predeclared operations.
  public Map<String, Object> getTransitiveBindings() {
    checkInitialized();
    // Can't use ImmutableMap.Builder because it doesn't allow duplicates.
    LinkedHashMap<String, Object> collectedBindings = new LinkedHashMap<>();
    if (universe != null) {
      collectedBindings.putAll(universe.getTransitiveBindings());
    }
    collectedBindings.putAll(getBindings());
    return collectedBindings;
  }

  /**
   * Returns the value of the specified module variable, or null if not bound. Does not look in the
   * predeclared environment.
   */
  public Object lookup(String varname) {
    checkInitialized();
    return bindings.get(varname);
  }

  /**
   * Returns the value of the named variable in the module environment, or if not bound there, in
   * the predeclared environment, or if not bound there, null.
   */
  public Object get(String varname) {
    // TODO(adonovan): delete this whole function, and getTransitiveBindings.
    // With proper resolution, the interpreter will know whether
    // to look in the module or the predeclared/universal environment.
    checkInitialized();
    Object val = bindings.get(varname);
    if (val != null) {
      return val;
    }
    if (universe != null) {
      return universe.get(varname);
    }
    return null;
  }

  /** Updates a binding in the module environment. */
  public void put(String varname, Object value) throws MutabilityException {
    Preconditions.checkNotNull(value, "Module.put(%s, null)", varname);
    checkInitialized();
    if (mutability.isFrozen()) {
      throw new MutabilityException("trying to mutate a frozen module");
    }
    bindings.put(varname, value);
  }

  @Override
  public String toString() {
    // TODO(adonovan): use the file name of the module (not visible to Starlark programs).
    if (mutability == null) {
      return "<Uninitialized Module>";
    } else {
      return String.format("<Module%s>", mutability());
    }
  }
}
