// Copyright 2023 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.analysis.starlark;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ActionsProvider;
import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RunEnvironmentInfo;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.packages.BuildGlobals;
import com.google.devtools.build.lib.packages.Proto;
import com.google.devtools.build.lib.packages.SelectorList;
import com.google.devtools.build.lib.packages.StarlarkGlobals;
import com.google.devtools.build.lib.packages.StarlarkNativeModule;
import com.google.devtools.build.lib.packages.StructProvider;
import net.starlark.java.eval.Starlark;
import net.starlark.java.lib.json.Json;

/**
 * Sole implementation of {@link StarlarkGlobals}.
 *
 * <p>The reason for the class-interface split is to allow {@link BazelStarlarkEnvironment} to
 * retrieve symbols defined and aggregated in the lib/analysis/ dir, without creating a dependency
 * from lib/packages/ to lib/analysis.
 */
public final class StarlarkGlobalsImpl implements StarlarkGlobals {

  private StarlarkGlobalsImpl() {}

  public static final StarlarkGlobalsImpl INSTANCE = new StarlarkGlobalsImpl();

  private void addCommonUtilToplevels(ImmutableMap.Builder<String, Object> env) {
    // Maintainer's note: Changes to this method are relatively high impact since it's sourced for
    // BUILD, .bzl, and even cquery environments.
    Starlark.addMethods(env, Depset.DepsetLibrary.INSTANCE);
    env.put("json", Json.INSTANCE);
    env.put("proto", Proto.INSTANCE);
  }

  @Override
  public ImmutableMap<String, Object> getUtilToplevels() {
    // TODO(bazel-team): It's dubious that we include things like depset and select(), but not
    // struct() here.
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    addCommonUtilToplevels(env);
    Starlark.addMethods(env, SelectorList.SelectLibrary.INSTANCE);
    return env.buildOrThrow();
  }

  @Override
  public ImmutableMap<String, Object> getUtilToplevelsForCquery() {
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    addCommonUtilToplevels(env);
    env.put("struct", StructProvider.STRUCT);
    return env.buildOrThrow();
  }

  @Override
  public ImmutableMap<String, Object> getFixedBuildFileToplevelsSharedWithNative() {
    return StarlarkNativeModule.BINDINGS_FOR_BUILD_FILES;
  }

  @Override
  public ImmutableMap<String, Object> getFixedBuildFileToplevelsNotInNative() {
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();

    env.putAll(getUtilToplevels());
    Starlark.addMethods(env, BuildGlobals.INSTANCE);

    return env.buildOrThrow();
  }

  @Override
  public ImmutableMap<String, Object> getFixedBzlToplevels() {
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();

    env.putAll(getUtilToplevels());

    Starlark.addMethods(env, new BazelBuildApiGlobals()); // e.g. configuration_field
    Starlark.addMethods(env, new StarlarkRuleClassFunctions()); // e.g. rule

    env.put("cmd_helper", new StarlarkCommandLine());
    env.put("attr", new StarlarkAttrModule());
    env.put("struct", StructProvider.STRUCT);
    env.put("OutputGroupInfo", OutputGroupInfo.STARLARK_CONSTRUCTOR);
    env.put("Actions", ActionsProvider.INSTANCE);
    env.put("DefaultInfo", DefaultInfo.PROVIDER);
    env.put("RunEnvironmentInfo", RunEnvironmentInfo.PROVIDER);

    return env.buildOrThrow();
  }

  @Override
  public ImmutableMap<String, Object> getSclToplevels() {
    // TODO(bazel-team): We only want the visibility() symbol from BazelBuildApiGlobals, nothing
    // else, but Starlark#addMethods doesn't allow that kind of granularity, and the Starlark
    // interpreter doesn't provide any other way to turn a Java method definition into a
    // callable symbol. So we hack it by building the map of all symbols in that class and
    // retrieving just the one we want. The alternative of refactoring the class is more churn than
    // its worth, given the starlarkbuildapi/ split.
    ImmutableMap.Builder<String, Object> bazelBuildApiGlobalsSymbols = ImmutableMap.builder();
    Starlark.addMethods(bazelBuildApiGlobalsSymbols, new BazelBuildApiGlobals());
    Object visibilitySymbol = bazelBuildApiGlobalsSymbols.buildOrThrow().get("visibility");

    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    env.put("visibility", visibilitySymbol);
    env.put("struct", StructProvider.STRUCT);
    return env.buildOrThrow();
  }
}
