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

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleInspectorValue.AugmentedModule;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleExtensionId;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
import com.google.devtools.build.lib.bazel.bzlmod.modcommand.ModuleArg.ModuleArgConverter;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.Label.RepoContext;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.server.FailureDetails.ModCommand.Code;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters.CommaSeparatedNonEmptyOptionListConverter;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.Optional;

/**
 * Represents a reference to a module extension, parsed from a command-line argument in the form of
 * {@code <module><bzl_file_label>%<extension_name>}. The {@code <module>} part is parsed as a
 * {@link ModuleArg}. Valid examples include {@code @rules_java//java:extensions.bzl%toolchains},
 * {@code rules_java@6.1.1//java:extensions.bzl%toolchains}, etc.
 */
@AutoValue
public abstract class ExtensionArg {
  public static ExtensionArg create(
      ModuleArg moduleArg, String repoRelativeBzlLabel, String extensionName) {
    return new AutoValue_ExtensionArg(moduleArg, repoRelativeBzlLabel, extensionName);
  }

  public abstract ModuleArg moduleArg();

  public abstract String repoRelativeBzlLabel();

  public abstract String extensionName();

  /** Resolves this {@link ExtensionArg} to a {@link ModuleExtensionId}. */
  public final ModuleExtensionId resolveToExtensionId(
      ImmutableMap<String, ImmutableSet<ModuleKey>> modulesIndex,
      ImmutableMap<ModuleKey, AugmentedModule> depGraph,
      ImmutableBiMap<String, ModuleKey> baseModuleDeps,
      ImmutableBiMap<String, ModuleKey> baseModuleUnusedDeps)
      throws InvalidArgumentException {
    ImmutableSet<ModuleKey> refModules =
        moduleArg()
            .resolveToModuleKeys(
                modulesIndex,
                depGraph,
                baseModuleDeps,
                baseModuleUnusedDeps,
                /* includeUnused= */ false,
                /* warnUnused= */ false);
    if (refModules.size() != 1) {
      throw new InvalidArgumentException(
          String.format(
              "Module %s, as part of the extension specifier, should represent exactly one module"
                  + " version. Choose one of: %s.",
              moduleArg(), refModules),
          Code.INVALID_ARGUMENTS);
    }
    ModuleKey key = Iterables.getOnlyElement(refModules);
    try {
      Label label =
          Label.parseWithRepoContext(
              repoRelativeBzlLabel(),
              RepoContext.of(
                  key.getCanonicalRepoName(),
                  // Intentionally allow no repo mapping here: it's a repo-relative label!
                  RepositoryMapping.create(ImmutableMap.of(), key.getCanonicalRepoName())));
      // TODO(wyv): support isolated extension usages?
      return ModuleExtensionId.create(label, extensionName(), Optional.empty());
    } catch (LabelSyntaxException e) {
      throw new InvalidArgumentException(
          String.format("bad label format in %s: %s", repoRelativeBzlLabel(), e.getMessage()),
          Code.INVALID_ARGUMENTS,
          e);
    }
  }

  @Override
  public final String toString() {
    return moduleArg() + repoRelativeBzlLabel() + "%" + extensionName();
  }

  /** Converter for {@link ExtensionArg}. */
  public static class ExtensionArgConverter extends Converter.Contextless<ExtensionArg> {
    public static final ExtensionArgConverter INSTANCE = new ExtensionArgConverter();

    @Override
    public ExtensionArg convert(String input) throws OptionsParsingException {
      int slashIdx = input.indexOf('/');
      if (slashIdx < 0) {
        throw new OptionsParsingException("Invalid argument " + input + ": missing .bzl label");
      }
      int percentIdx = input.indexOf('%');
      if (percentIdx < slashIdx) {
        throw new OptionsParsingException("Invalid argument " + input + ": missing extension name");
      }
      ModuleArg moduleArg = ModuleArgConverter.INSTANCE.convert(input.substring(0, slashIdx));
      return ExtensionArg.create(
          moduleArg, input.substring(slashIdx, percentIdx), input.substring(percentIdx + 1));
    }

    @Override
    public String getTypeDescription() {
      return "an <extension> identifier in the format of <module><bzl_label>%<extension_name>";
    }
  }

  /** Converter for a comma-separated list of {@link ExtensionArg}s. */
  public static class CommaSeparatedExtensionArgListConverter
      extends Converter.Contextless<ImmutableList<ExtensionArg>> {

    @Override
    public ImmutableList<ExtensionArg> convert(String input) throws OptionsParsingException {
      ImmutableList<String> args = new CommaSeparatedNonEmptyOptionListConverter().convert(input);
      ImmutableList.Builder<ExtensionArg> extensionArgs = new ImmutableList.Builder<>();
      for (String arg : args) {
        extensionArgs.add(ExtensionArgConverter.INSTANCE.convert(arg));
      }
      return extensionArgs.build();
    }

    @Override
    public String getTypeDescription() {
      return "a comma-separated list of <extension>s";
    }
  }
}
