// 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.rules.starlarkdocextract;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleClassFunctions.StarlarkRuleFunction;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.StarlarkDefinedAspect;
import com.google.devtools.build.lib.packages.StarlarkProvider;
import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.skydoc.rendering.DocstringParseException;
import com.google.devtools.build.skydoc.rendering.FunctionUtil;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeType;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderFieldInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderNameGroup;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Module;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.Structure;

/** API documentation extractor for a compiled, loaded Starlark module. */
final class ModuleInfoExtractor {
  private final Predicate<String> isWantedName;
  private final RepositoryMapping repositoryMapping;

  @VisibleForTesting
  static final AttributeInfo IMPLICIT_NAME_ATTRIBUTE_INFO =
      AttributeInfo.newBuilder()
          .setName("name")
          .setType(AttributeType.NAME)
          .setMandatory(true)
          .setDocString("A unique name for this target.")
          .build();

  // TODO(b/276733504): do we want to add an implicit repo_mapping attribute for repo rules, as
  // FakeRepositoryModule currently does?

  /**
   * Constructs an instance of {@code ModuleInfoExtractor}.
   *
   * @param isWantedName a filter applied to symbols names; only those symbols which both are
   *     exportable (meaning the first character is alphabetic) and for which the filter returns
   *     true will be documented
   * @param repositoryMapping the repository mapping for the repo in which we want to render labels
   *     as strings
   */
  public ModuleInfoExtractor(Predicate<String> isWantedName, RepositoryMapping repositoryMapping) {
    this.isWantedName = isWantedName;
    this.repositoryMapping = repositoryMapping;
  }

  /** Extracts structured documentation for the exported symbols of a given module. */
  public ModuleInfo extractFrom(Module module) throws ExtractionException {
    ModuleInfo.Builder builder = ModuleInfo.newBuilder();
    Optional.ofNullable(module.getDocumentation()).ifPresent(builder::setModuleDocstring);
    for (var entry : module.getGlobals().entrySet()) {
      String topLevelSymbol = entry.getKey();
      if (isExportableName(topLevelSymbol) && isWantedName.test(topLevelSymbol)) {
        addInfo(builder, topLevelSymbol, entry.getValue());
      }
    }
    return builder.build();
  }

  private static boolean isExportableName(String name) {
    return name.length() > 0 && Character.isAlphabetic(name.charAt(0));
  }

  /** An exception indicating that the module's API documentation could not be extracted. */
  public static class ExtractionException extends Exception {
    public ExtractionException(String message) {
      super(message);
    }

    public ExtractionException(Throwable cause) {
      super(cause);
    }

    public ExtractionException(String message, Throwable cause) {
      super(message, cause);
    }
  }

  /**
   * @param builder proto builder to which to append documentation
   * @param name the name under which the value is exported by the module; for example, "foo.bar"
   *     for field bar of exported struct foo
   * @param value documentable Starlark value
   */
  private void addInfo(ModuleInfo.Builder builder, String name, Object value)
      throws ExtractionException {
    if (value instanceof StarlarkRuleFunction) {
      addRuleInfo(builder, name, (StarlarkRuleFunction) value);
    } else if (value instanceof StarlarkProvider) {
      addProviderInfo(builder, name, (StarlarkProvider) value);
    } else if (value instanceof StarlarkFunction) {
      try {
        builder.addFuncInfo(FunctionUtil.fromNameAndFunction(name, (StarlarkFunction) value));
      } catch (DocstringParseException e) {
        throw new ExtractionException(e);
      }
    } else if (value instanceof StarlarkDefinedAspect) {
      addAspectInfo(builder, name, (StarlarkDefinedAspect) value);
    } else if (value instanceof Structure) {
      addStructureInfo(builder, name, (Structure) value);
    }
    // else the value is a constant (string, list etc.), and we currently don't have a convention
    // for associating a doc string with one - so we don't emit documentation for it.
    // TODO(b/276733504): should we recurse into dicts to search for documentable values?
  }

  private void addStructureInfo(ModuleInfo.Builder builder, String name, Structure structure)
      throws ExtractionException {
    for (String fieldName : structure.getFieldNames()) {
      if (isExportableName(fieldName)) {
        try {
          Object fieldValue = structure.getValue(fieldName);
          if (fieldValue != null) {
            addInfo(builder, String.format("%s.%s", name, fieldName), fieldValue);
          }
        } catch (EvalException e) {
          throw new ExtractionException(
              String.format("in struct %s field %s: failed to read value", name, fieldName), e);
        }
      }
    }
  }

  private static AttributeType getAttributeType(Attribute attribute, String where)
      throws ExtractionException {
    Type<?> type = attribute.getType();
    if (type.equals(Type.INTEGER)) {
      return AttributeType.INT;
    } else if (type.equals(BuildType.LABEL)) {
      return AttributeType.LABEL;
    } else if (type.equals(Type.STRING)) {
      if (attribute.getPublicName().equals("name")) {
        return AttributeType.NAME;
      } else {
        return AttributeType.STRING;
      }
    } else if (type.equals(Type.STRING_LIST)) {
      return AttributeType.STRING_LIST;
    } else if (type.equals(Type.INTEGER_LIST)) {
      return AttributeType.INT_LIST;
    } else if (type.equals(BuildType.LABEL_LIST)) {
      return AttributeType.LABEL_LIST;
    } else if (type.equals(Type.BOOLEAN)) {
      return AttributeType.BOOLEAN;
    } else if (type.equals(BuildType.LABEL_KEYED_STRING_DICT)) {
      return AttributeType.LABEL_STRING_DICT;
    } else if (type.equals(Type.STRING_DICT)) {
      return AttributeType.STRING_DICT;
    } else if (type.equals(Type.STRING_LIST_DICT)) {
      return AttributeType.STRING_LIST_DICT;
    } else if (type.equals(BuildType.OUTPUT)) {
      return AttributeType.OUTPUT;
    } else if (type.equals(BuildType.OUTPUT_LIST)) {
      return AttributeType.OUTPUT_LIST;
    }

    throw new ExtractionException(
        String.format(
            "in %s attribute %s: unsupported type %s",
            where, attribute.getPublicName(), type.getClass().getSimpleName()));
  }

  /**
   * Recursively transforms labels to strings via {@link Label#getShorthandDisplayForm}.
   *
   * @return the label's shorthand display string if {@code o} is a label; a container with label
   *     elements transformed into shorthand display strings recursively if {@code o} is a Starlark
   *     container; or the original object {@code o} if no label stringification was performed.
   */
  private Object stringifyLabels(Object o) {
    if (o instanceof Label) {
      return ((Label) o).getShorthandDisplayForm(repositoryMapping);
    } else if (o instanceof Map) {
      return stringifyLabelsOfMap((Map<?, ?>) o);
    } else if (o instanceof List) {
      return stringifyLabelsOfList((List<?>) o);
    } else {
      return o;
    }
  }

  private Object stringifyLabelsOfMap(Map<?, ?> dict) {
    boolean neededToStringify = false;
    ImmutableMap.Builder<Object, Object> builder = ImmutableMap.builder();
    for (Map.Entry<?, ?> entry : dict.entrySet()) {
      Object keyWithStringifiedLabels = stringifyLabels(entry.getKey());
      Object valueWithStringifiedLabels = stringifyLabels(entry.getValue());
      if (keyWithStringifiedLabels != entry.getKey()
          || valueWithStringifiedLabels != entry.getValue() /* as Objects */) {
        neededToStringify = true;
      }
      builder.put(keyWithStringifiedLabels, valueWithStringifiedLabels);
    }
    return neededToStringify ? Dict.immutableCopyOf(builder.buildOrThrow()) : dict;
  }

  private Object stringifyLabelsOfList(List<?> list) {
    boolean neededToStringify = false;
    ImmutableList.Builder<Object> builder = ImmutableList.builder();
    for (Object element : list) {
      Object elementWithStringifiedLabels = stringifyLabels(element);
      if (elementWithStringifiedLabels != element /* as Objects */) {
        neededToStringify = true;
      }
      builder.add(elementWithStringifiedLabels);
    }
    return neededToStringify ? StarlarkList.immutableCopyOf(builder.build()) : list;
  }

  private AttributeInfo buildAttributeInfo(Attribute attribute, String where)
      throws ExtractionException {
    AttributeInfo.Builder builder = AttributeInfo.newBuilder();
    builder.setName(attribute.getPublicName());
    Optional.ofNullable(attribute.getDoc()).ifPresent(builder::setDocString);
    builder.setType(getAttributeType(attribute, where));
    builder.setMandatory(attribute.isMandatory());
    for (ImmutableSet<StarlarkProviderIdentifier> providerGroup :
        attribute.getRequiredProviders().getStarlarkProviders()) {
      ProviderNameGroup.Builder providerNameGroupBuilder = ProviderNameGroup.newBuilder();
      for (StarlarkProviderIdentifier provider : providerGroup) {
        // TODO(b/276733504): if this module exports a provider under a different name or in a
        // namespace, document it under that exported name rather than the provider's key name.
        providerNameGroupBuilder.addProviderName(provider.toString());
      }
      builder.addProviderNameGroup(providerNameGroupBuilder.build());
    }

    if (!attribute.isMandatory()) {
      Object defaultValue = Attribute.valueToStarlark(attribute.getDefaultValueUnchecked());
      builder.setDefaultValue(new Printer().repr(stringifyLabels(defaultValue)).toString());
    }
    return builder.build();
  }

  private void addRuleInfo(
      ModuleInfo.Builder moduleInfoBuilder, String exportedName, StarlarkRuleFunction ruleFunction)
      throws ExtractionException {
    RuleInfo.Builder ruleInfoBuilder = RuleInfo.newBuilder();
    // Allow rules to be exported under a different name (e.g. in a struct).
    ruleInfoBuilder.setRuleName(exportedName);
    ruleFunction.getDocumentation().ifPresent(ruleInfoBuilder::setDocString);
    RuleClass ruleClass = ruleFunction.getRuleClass();
    ruleInfoBuilder.addAttribute(IMPLICIT_NAME_ATTRIBUTE_INFO); // name comes first
    for (Attribute attribute : ruleClass.getAttributes()) {
      if (attribute.starlarkDefined()
          && attribute.isDocumented()
          && isExportableName(attribute.getPublicName())) {
        ruleInfoBuilder.addAttribute(buildAttributeInfo(attribute, "rule " + exportedName));
      }
    }
    moduleInfoBuilder.addRuleInfo(ruleInfoBuilder);
  }

  private static void addProviderInfo(
      ModuleInfo.Builder moduleInfoBuilder, String exportedName, StarlarkProvider provider) {
    ProviderInfo.Builder providerInfoBuilder = ProviderInfo.newBuilder();
    // Allow providers to be exported under a different name (e.g. in a struct).
    providerInfoBuilder.setProviderName(exportedName);
    provider.getDocumentation().ifPresent(providerInfoBuilder::setDocString);
    ImmutableMap<String, Optional<String>> schemaWithDocumentation =
        provider.getSchemaWithDocumentation();
    if (schemaWithDocumentation != null) {
      for (Map.Entry<String, Optional<String>> entry : schemaWithDocumentation.entrySet()) {
        if (isExportableName(entry.getKey())) {
          ProviderFieldInfo.Builder fieldInfoBuilder = ProviderFieldInfo.newBuilder();
          fieldInfoBuilder.setName(entry.getKey());
          entry.getValue().ifPresent(fieldInfoBuilder::setDocString);
          providerInfoBuilder.addFieldInfo(fieldInfoBuilder.build());
        }
      }
    }
    moduleInfoBuilder.addProviderInfo(providerInfoBuilder);
  }

  private void addAspectInfo(
      ModuleInfo.Builder moduleInfoBuilder, String exportedName, StarlarkDefinedAspect aspect)
      throws ExtractionException {
    AspectInfo.Builder aspectInfoBuilder = AspectInfo.newBuilder();
    // Allow aspects to be exported under a different name (e.g. in a struct).
    aspectInfoBuilder.setAspectName(exportedName);
    aspect.getDocumentation().ifPresent(aspectInfoBuilder::setDocString);
    aspectInfoBuilder.addAllAspectAttribute(aspect.getAttributeAspects());
    aspectInfoBuilder.addAttribute(IMPLICIT_NAME_ATTRIBUTE_INFO); // name comes first
    for (Attribute attribute : aspect.getAttributes()) {
      if (isExportableName(attribute.getPublicName())) {
        aspectInfoBuilder.addAttribute(buildAttributeInfo(attribute, "aspect " + exportedName));
      }
    }
    moduleInfoBuilder.addAspectInfo(aspectInfoBuilder);
  }
}
