// Copyright 2021 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.bazel.bzlmod;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
import com.google.devtools.build.lib.packages.StarlarkNativeModule.ExistingRulesShouldBeNoOp;
import java.util.HashMap;
import java.util.Map;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/**
 * A context object that should be stored in a {@link StarlarkThread} for use during module
 * extension evaluation.
 */
public final class ModuleExtensionEvalStarlarkThreadContext {
  public void storeInThread(StarlarkThread thread) {
    thread.setThreadLocal(ModuleExtensionEvalStarlarkThreadContext.class, this);
    // The following is just a hack; see documentation there for an explanation.
    thread.setThreadLocal(ExistingRulesShouldBeNoOp.class, new ExistingRulesShouldBeNoOp());
  }

  public static ModuleExtensionEvalStarlarkThreadContext from(StarlarkThread thread) {
    return thread.getThreadLocal(ModuleExtensionEvalStarlarkThreadContext.class);
  }

  @AutoValue
  abstract static class RepoSpecAndLocation {
    abstract RepoSpec getRepoSpec();

    abstract Location getLocation();

    static RepoSpecAndLocation create(RepoSpec repoSpec, Location location) {
      return new AutoValue_ModuleExtensionEvalStarlarkThreadContext_RepoSpecAndLocation(
          repoSpec, location);
    }
  }

  private final String repoPrefix;
  private final PackageIdentifier basePackageId;
  private final RepositoryMapping repoMapping;
  private final BlazeDirectories directories;
  private final ExtendedEventHandler eventHandler;
  private final Map<String, RepoSpecAndLocation> generatedRepos = new HashMap<>();

  public ModuleExtensionEvalStarlarkThreadContext(
      String repoPrefix,
      PackageIdentifier basePackageId,
      RepositoryMapping repoMapping,
      BlazeDirectories directories,
      ExtendedEventHandler eventHandler) {
    this.repoPrefix = repoPrefix;
    this.basePackageId = basePackageId;
    this.repoMapping = repoMapping;
    this.directories = directories;
    this.eventHandler = eventHandler;
  }

  public void createRepo(StarlarkThread thread, Dict<String, Object> kwargs, RuleClass ruleClass)
      throws InterruptedException, EvalException {
    Object nameValue = kwargs.getOrDefault("name", Starlark.NONE);
    if (!(nameValue instanceof String)) {
      throw Starlark.errorf(
          "expected string for attribute 'name', got '%s'", Starlark.type(nameValue));
    }
    String name = (String) nameValue;
    RepositoryName.validateUserProvidedRepoName(name);
    RepoSpecAndLocation conflict = generatedRepos.get(name);
    if (conflict != null) {
      throw Starlark.errorf(
          "A repo named %s is already generated by this module extension at %s",
          name, conflict.getLocation());
    }
    String prefixedName = repoPrefix + name;
    try {
      Rule rule =
          BzlmodRepoRuleCreator.createRule(
              basePackageId,
              repoMapping,
              directories,
              thread.getSemantics(),
              eventHandler,
              "RepositoryRuleFunction.createRule",
              ruleClass,
              Maps.transformEntries(kwargs, (k, v) -> k.equals("name") ? prefixedName : v));

      Map<String, Object> attributes = Maps.transformEntries(kwargs, (k, v) -> rule.getAttr(k));
      String bzlFile = ruleClass.getRuleDefinitionEnvironmentLabel().getUnambiguousCanonicalForm();
      RepoSpec repoSpec =
          RepoSpec.builder()
              .setBzlFile(bzlFile)
              .setRuleClassName(ruleClass.getName())
              .setAttributes(AttributeValues.create(attributes))
              .build();

      generatedRepos.put(name, RepoSpecAndLocation.create(repoSpec, thread.getCallerLocation()));
    } catch (InvalidRuleException | NoSuchPackageException e) {
      throw Starlark.errorf("%s", e.getMessage());
    }
  }

  /**
   * Returns the repos generated by the extension so far. The key is the "internal name" (as
   * specified by the extension) of the repo, and the value is the package containing (only) the
   * repo rule.
   */
  public ImmutableMap<String, RepoSpec> getGeneratedRepoSpecs() {
    return ImmutableMap.copyOf(
        Maps.transformValues(generatedRepos, RepoSpecAndLocation::getRepoSpec));
  }
}
