// Copyright 2018 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.skyframe;

import com.google.auto.value.AutoValue;
import com.google.devtools.build.lib.bazel.bzlmod.Version;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Map;
import java.util.Optional;

/**
 * A value that represents the 'mappings' of an external Bazel workspace, as defined in the main
 * WORKSPACE file. The SkyValue contains the mappings themselves, with the key being the name of the
 * external repository.
 *
 * <p>Given the following rule:
 *
 * <pre>{@code
 * local_repository(
 *   name = "a",
 *   path = "../a",
 *   repo_mapping = {"@x" : "@y"}
 * )
 * }</pre>
 *
 * <p>The SkyKey would be {@code "@a"} and the SkyValue would be the map {@code {"@x" : "@y"}}
 *
 * <p>This is kept as a separate value with trivial change pruning so as to not necessitate a
 * dependency from every {@link PackageValue} to the //external {@link PackageValue}, so that
 * changes to things in the WORKSPACE other than the mappings (and name) won't require reloading all
 * packages. If the mappings are changed then the external packages need to be reloaded.
 */
@AutoValue
public abstract class RepositoryMappingValue implements SkyValue {
  public static final Key KEY_FOR_ROOT_MODULE_WITHOUT_WORKSPACE_REPOS =
      Key.create(RepositoryName.MAIN, /* rootModuleShouldSeeWorkspaceRepos= */ false);

  public static final RepositoryMappingValue VALUE_FOR_ROOT_MODULE_WITHOUT_REPOS =
      RepositoryMappingValue.createForWorkspaceRepo(RepositoryMapping.ALWAYS_FALLBACK);

  /**
   * Returns a {@link RepositoryMappingValue} for a repo defined in MODULE.bazel, which has an
   * associated module.
   */
  public static RepositoryMappingValue createForBzlmodRepo(
      RepositoryMapping repositoryMapping,
      String associatedModuleName,
      Version associatedModuleVersion) {
    return new AutoValue_RepositoryMappingValue(
        repositoryMapping,
        Optional.of(associatedModuleName),
        Optional.of(associatedModuleVersion.getOriginal()));
  }

  /**
   * Returns a {@link RepositoryMappingValue} for a repo defined in WORKSPACE, which has no
   * associated module.
   */
  public static RepositoryMappingValue createForWorkspaceRepo(RepositoryMapping repositoryMapping) {
    return new AutoValue_RepositoryMappingValue(
        repositoryMapping, Optional.empty(), Optional.empty());
  }

  public abstract RepositoryMapping getRepositoryMapping();

  /**
   * Returns the name of the Bzlmod module associated with the requested repo. If the requested repo
   * is defined in WORKSPACE, this is empty. For repos generated by module extensions, this is the
   * name of the module hosting the extension.
   */
  public abstract Optional<String> getAssociatedModuleName();

  /**
   * Returns the version of the Bzlmod module associated with the requested repo. If the requested
   * repo is defined in WORKSPACE, this is empty. For repos generated by module extensions, this is
   * the version of the module hosting the extension.
   */
  public abstract Optional<String> getAssociatedModuleVersion();

  /**
   * Replaces the inner {@link #getRepositoryMapping() repository mapping} with one returned by
   * calling its {@link RepositoryMapping#withAdditionalMappings} method.
   */
  public final RepositoryMappingValue withAdditionalMappings(Map<String, RepositoryName> mappings) {
    return new AutoValue_RepositoryMappingValue(
        getRepositoryMapping().withAdditionalMappings(mappings),
        getAssociatedModuleName(),
        getAssociatedModuleVersion());
  }

  /** Returns the {@link Key} for {@link RepositoryMappingValue}s. */
  public static Key key(RepositoryName repositoryName) {
    return RepositoryMappingValue.Key.create(
        repositoryName, /* rootModuleShouldSeeWorkspaceRepos= */ true);
  }

  /** {@link SkyKey} for {@link RepositoryMappingValue}. */
  @AutoValue
  public abstract static class Key implements SkyKey {

    private static final SkyKeyInterner<Key> interner = SkyKey.newInterner();

    /** The name of the repo to grab mappings for. */
    public abstract RepositoryName repoName();

    /**
     * Whether the root module should see repos defined in WORKSPACE. This only takes effect when
     * {@link #repoName} is the main repo.
     */
    abstract boolean rootModuleShouldSeeWorkspaceRepos();

    @AutoCodec.Instantiator
    static Key create(RepositoryName repoName, boolean rootModuleShouldSeeWorkspaceRepos) {
      return interner.intern(
          new AutoValue_RepositoryMappingValue_Key(repoName, rootModuleShouldSeeWorkspaceRepos));
    }

    @Override
    public SkyFunctionName functionName() {
      return SkyFunctions.REPOSITORY_MAPPING;
    }

    @Override
    public SkyKeyInterner<Key> getSkyKeyInterner() {
      return interner;
    }
  }

  /**
   * Exception thrown where the RepositoryMappingValue is requested and its computation fails for
   * any reason.
   */
  public static class RepositoryMappingResolutionException extends Exception {

    private final DetailedExitCode detailedExitCode;

    public RepositoryMappingResolutionException(DetailedExitCode detailedExitCode) {
      super(
          String.format(
              "Error computing the main repository mapping: %s",
              detailedExitCode.getFailureDetail().getMessage()));
      this.detailedExitCode = detailedExitCode;
    }

    public RepositoryMappingResolutionException(
        DetailedExitCode detailedExitCode, Throwable cause) {
      super(
          String.format(
              "Error computing the main repository mapping: %s",
              detailedExitCode.getFailureDetail().getMessage()),
          cause);
      this.detailedExitCode = detailedExitCode;
    }

    public ExitCode getExitCode() {
      return detailedExitCode.getExitCode();
    }

    public DetailedExitCode getDetailedExitCode() {
      return detailedExitCode;
    }
  }
}
