// 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 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 Resolver.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 EvalException {
    Preconditions.checkNotNull(value, "Module.put(%s, null)", varname);
    checkInitialized();
    if (mutability.isFrozen()) {
      throw Starlark.errorf("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());
    }
  }
}
