// 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.Map.Entry;
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.
// - eliminate Frame interface and the methods it forces upon Module.
// - separate the universal predeclared environment and make it implicit.
// - eliminate initialize(). The only constructor we need is:
//   (Mutability mu, Map<String, Object> predeclared, Object label).
public final class Module implements StarlarkThread.Frame, 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<>();
  }

  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);
    }
    Map<String, Object> filteredBindings = new LinkedHashMap<>();
    Map<String, FlagGuardedValue> restrictedBindings = new LinkedHashMap<>();

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

    restrictedBindings.putAll(parent.restrictedBindings);

    return new Module(
        mutability, null /*parent */, 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}. */
  @Override
  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`).
   */
  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(StarlarkSemantics semantics, String name) {
    FlagGuardedValue v = restrictedBindings.get(name);
    return v == null ? null : v.getErrorFromAttemptingAccess(semantics, name);
  }

  @Override
  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;
  }

  public Object getDirectBindings(String varname) {
    checkInitialized();
    return bindings.get(varname);
  }

  @Override
  public Object get(String varname) {
    checkInitialized();
    Object val = bindings.get(varname);
    if (val != null) {
      return val;
    }
    if (universe != null) {
      return universe.get(varname);
    }
    return null;
  }

  @Override
  public void put(String varname, Object value) throws MutabilityException {
    checkInitialized();
    Mutability.checkMutable(this, mutability());
    bindings.put(varname, value);
  }

  @Override
  public void remove(String varname) throws MutabilityException {
    checkInitialized();
    Mutability.checkMutable(this, mutability());
    bindings.remove(varname);
  }

  @Override
  public String toString() {
    if (mutability == null) {
      return "<Uninitialized Module>";
    } else {
      return String.format("<Module%s>", mutability());
    }
  }
}
