// Copyright 2014 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.docgen;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Types;
import com.google.devtools.build.skydoc.rendering.LabelRenderer;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A class storing a rule attribute documentation along with some meta information. For native
 * attributes, the class provides functionality to compute the ancestry level of this attribute's
 * generator rule definition class compared to other rule definition classes.
 *
 * <p>Warning, two RuleDocumentationAttribute objects are equal based on only the attributeName.
 */
public class RuleDocumentationAttribute
    implements Comparable<RuleDocumentationAttribute>, Cloneable {

  private static final ImmutableMap<Type<?>, String> TYPE_DESC =
      ImmutableMap.<Type<?>, String>builder()
          .put(Type.BOOLEAN, "Boolean")
          .put(Type.INTEGER, "Integer")
          .put(Types.INTEGER_LIST, "List of integers")
          .put(Type.STRING, "String")
          .put(Types.STRING_DICT, "Dictionary: String -> String")
          .put(Types.STRING_LIST, "List of strings")
          .put(BuildType.TRISTATE, "Integer")
          .put(BuildType.LABEL, "<a href=\"${link build-ref#labels}\">Label</a>")
          .put(
              BuildType.LABEL_KEYED_STRING_DICT,
              "Dictionary: <a href=\"${link build-ref#labels}\">label</a> -> String")
          .put(BuildType.LABEL_LIST, "List of <a href=\"${link build-ref#labels}\">labels</a>")
          .put(
              BuildType.GENQUERY_SCOPE_TYPE_LIST,
              "List of <a href=\"${link build-ref#labels}\">labels</a>")
          .put(
              BuildType.LABEL_DICT_UNARY,
              "Dictionary mapping strings to <a href=\"${link build-ref#labels}\">labels</a>")
          .put(BuildType.LICENSE, "Licence type")
          .put(BuildType.NODEP_LABEL, "<a href=\"${link build-ref#name}\">Name</a>")
          .put(BuildType.NODEP_LABEL_LIST, "List of <a href=\"${link build-ref#name}\">names</a>")
          .put(BuildType.OUTPUT, "<a href=\"${link build-ref#filename}\">Filename</a>")
          .put(
              BuildType.OUTPUT_LIST, "List of <a href=\"${link build-ref#filename}\">filenames</a>")
          .buildOrThrow();

  @Nullable private final Class<? extends RuleDefinition> definitionClass;
  private final String attributeName;
  private final String htmlDocumentation;
  @Nullable private final String commonType;
  // Used to expand rule link references in the attribute documentation.
  private RuleLinkExpander linkExpander;
  private final String location; // for error messages
  private Set<String> flags;
  // The following are not set by create() or createCommon()
  @Nullable private final Type<?> type;
  @Nullable private final String defaultValue;
  private final boolean mandatory;
  private final boolean nonconfigurable;

  /**
   * Creates a RuleDocumentationAttribute from comments in Java sources. Additional metadata may be
   * filled in later via {@link copyAndUpdateFrom}.
   */
  static RuleDocumentationAttribute create(
      @Nullable Class<? extends RuleDefinition> definitionClass,
      String attributeName,
      String htmlDocumentation,
      String file,
      int lineNumber,
      Set<String> flags) {
    return new RuleDocumentationAttribute(
        definitionClass,
        attributeName,
        htmlDocumentation,
        BuildEncyclopediaDocException.formatLocation(file, lineNumber),
        flags,
        /* commonType= */ null,
        /* type= */ null,
        /* defaultValue= */ null,
        /* mandatory= */ false,
        /* nonconfigurable= */ false);
  }

  /**
   * Creates common RuleDocumentationAttribute such as deps or data. These attribute docs have no
   * definitionClass or htmlDocumentation (it's in the BE header).
   */
  static RuleDocumentationAttribute createCommon(
      String attributeName, String commonType, String htmlDocumentation) {
    return new RuleDocumentationAttribute(
        null,
        attributeName,
        htmlDocumentation,
        "",
        ImmutableSet.of(),
        commonType,
        /* type= */ null,
        /* defaultValue= */ null,
        /* mandatory= */ false,
        /* nonconfigurable= */ false);
  }

  /** Creates a RuleDocumentationAttribute from a stardoc_output.AttributeInfo proto. */
  static RuleDocumentationAttribute createFromAttributeInfo(
      AttributeInfo attributeInfo, String location, Set<String> flags)
      throws BuildEncyclopediaDocException {
    return new RuleDocumentationAttribute(
        null,
        attributeInfo.getName(),
        attributeInfo.getDocString(),
        location,
        flags,
        /* commonType= */ null,
        getAttributeInfoType(attributeInfo, location),
        attributeInfo.getDefaultValue(),
        attributeInfo.getMandatory(),
        attributeInfo.getNonconfigurable());
  }

  /**
   * Copies this RuleDocumentationAttribute and sets additional metadata (type, default value, and
   * whether the attribute is mandatory or nonconfigurable) from a native attribute object.
   */
  RuleDocumentationAttribute copyAndUpdateFrom(Attribute attribute) {
    return new RuleDocumentationAttribute(
        this.definitionClass,
        this.attributeName,
        this.htmlDocumentation,
        this.location,
        this.flags,
        this.commonType,
        attribute.getType(),
        reprDefaultValue(attribute),
        attribute.isMandatory(),
        !attribute.isConfigurable());
  }

  private static Type<?> getAttributeInfoType(AttributeInfo attributeInfo, String location)
      throws BuildEncyclopediaDocException {
    switch (attributeInfo.getType()) {
      case INT:
        return Type.INTEGER;
      case LABEL:
        return BuildType.LABEL;
      case NAME:
      case STRING:
        return Type.STRING;
      case STRING_LIST:
        return Types.STRING_LIST;
      case INT_LIST:
        return Types.INTEGER_LIST;
      case LABEL_LIST:
        return BuildType.LABEL_LIST;
      case BOOLEAN:
        return Type.BOOLEAN;
      case LABEL_STRING_DICT:
        return BuildType.LABEL_KEYED_STRING_DICT;
      case STRING_DICT:
        return Types.STRING_DICT;
      case STRING_LIST_DICT:
        return Types.STRING_LIST_DICT;
      case OUTPUT:
        return BuildType.OUTPUT;
      case OUTPUT_LIST:
        return BuildType.OUTPUT_LIST;
      default:
        throw new BuildEncyclopediaDocException(
            location,
            String.format(
                "attribute %s: unknown type %s", attributeInfo.getName(), attributeInfo.getType()));
    }
  }

  private RuleDocumentationAttribute(
      @Nullable Class<? extends RuleDefinition> definitionClass,
      String attributeName,
      String htmlDocumentation,
      String location,
      Set<String> flags,
      @Nullable String commonType,
      @Nullable Type<?> type,
      @Nullable String defaultValue,
      boolean mandatory,
      boolean nonconfigurable) {
    Preconditions.checkNotNull(attributeName, "AttributeName must not be null.");
    this.definitionClass = definitionClass;
    this.attributeName = attributeName;
    this.htmlDocumentation = htmlDocumentation;
    this.location = location;
    this.flags = flags;
    this.commonType = commonType;
    this.type = type;
    this.defaultValue = defaultValue;
    this.mandatory = mandatory;
    this.nonconfigurable = nonconfigurable;
  }

  @Nullable
  private static String reprDefaultValue(Attribute attribute) {
    Object value = attribute.getDefaultValueUnchecked();
    if (value instanceof ComputedDefault || value instanceof StarlarkComputedDefaultTemplate) {
      // We cannot print anything useful here other than "optional". Let's assume the doc string for
      // the attribute explains the details.
      return null;
    } else if (value instanceof TriState triState) {
      switch (triState) {
        case AUTO:
          return "-1";
        case NO:
          return "0";
        case YES:
          return "1";
      }
    }
    return LabelRenderer.DEFAULT.reprWithoutLabelConstructor(Attribute.valueToStarlark(value));
  }

  /**
   * Returns the name of the rule attribute.
   */
  public String getAttributeName() {
    return attributeName;
  }

  /**
   * Returns the file name or label, optionally with a line number, where the rule attribute is
   * defined.
   */
  public String getLocation() {
    return location;
  }

  /**
   * Returns whether this attribute is marked as deprecated.
   */
  public boolean isDeprecated() {
    return hasFlag(DocgenConsts.FLAG_DEPRECATED);
  }

  /**
   * Sets the {@link RuleLinkExpander} to be used to expand links in the HTML documentation.
   */
  public void setRuleLinkExpander(RuleLinkExpander linkExpander) {
    this.linkExpander = linkExpander;
  }

  /**
   * Returns the html documentation of the rule attribute.
   */
  public String getHtmlDocumentation() throws BuildEncyclopediaDocException {
    return tryExpand(htmlDocumentation);
  }

  public String tryExpand(String html) throws BuildEncyclopediaDocException {
    if (linkExpander == null) {
      return html;
    }
    try {
      return linkExpander.expand(html);
    } catch (IllegalArgumentException e) {
      throw new BuildEncyclopediaDocException(location, e.getMessage());
    }
  }

  /** Returns whether the param is required or optional. */
  public boolean isMandatory() {
    return mandatory;
  }

  /** Returns a string containing the synopsis for this attribute. */
  public String getSynopsis() throws BuildEncyclopediaDocException {
    if (type == null) {
      return "";
    }
    String rawType = TYPE_DESC.get(type);
    StringBuilder sb =
        new StringBuilder()
            .append(rawType == null ? null : tryExpand(rawType))
            .append(
                nonconfigurable
                    ? String.format(
                        "; <a href=\"%s#configurable-attributes\">nonconfigurable</a>",
                        RuleDocumentation.COMMON_DEFINITIONS_PAGE)
                    : "");
    if (isMandatory()) {
      sb.append("; required");
    } else if (defaultValue != null && !defaultValue.isEmpty()) {
      sb.append("; default is <code>").append(defaultValue).append("</code>");
    } else {
      // Computed default or other non-representable value
      sb.append("; optional");
    }
    return sb.toString();
  }

  /**
   * Returns true if the attribute doc is of a common attribute type.
   */
  public boolean isCommonType() {
    return commonType != null;
  }

  /**
   * Returns the common attribute type if this attribute doc is of a common type
   * otherwise actualRule.
   */
  String getGeneratedInRule(String actualRule) {
    return isCommonType() ? commonType : actualRule;
  }

  /**
   * Returns true if this attribute documentation has the parameter flag.
   */
  boolean hasFlag(String flag) {
    return flags.contains(flag);
  }

  /**
   * Returns the length of a shortest path from usingClass to the definitionClass of this
   * RuleDocumentationAttribute in the rule definition ancestry graph. Returns -1
   * if definitionClass is not the ancestor (transitively) of usingClass.
   */
  int getDefinitionClassAncestryLevel(Class<? extends RuleDefinition> usingClass,
      ConfiguredRuleClassProvider ruleClassProvider) {
    if (usingClass.equals(definitionClass)) {
      return 0;
    }
    // Storing nodes (rule class definitions) with the length of the shortest path from usingClass
    Map<Class<? extends RuleDefinition>, Integer> visited = new HashMap<>();
    LinkedList<Class<? extends RuleDefinition>> toVisit = new LinkedList<>();
    visited.put(usingClass, 0);
    toVisit.add(usingClass);
    // Searching the shortest path from usingClass to this.definitionClass using BFS
    do {
      Class<? extends RuleDefinition> ancestor = toVisit.removeFirst();
      visitAncestor(ancestor, visited, toVisit, ruleClassProvider);
      if (ancestor.equals(definitionClass)) {
        return visited.get(ancestor);
      }
    } while (!toVisit.isEmpty());
    return -1;
  }

  private void visitAncestor(
      Class<? extends RuleDefinition> usingClass,
      Map<Class<? extends RuleDefinition>, Integer> visited,
      LinkedList<Class<? extends RuleDefinition>> toVisit,
      ConfiguredRuleClassProvider ruleClassProvider) {
    RuleDefinition instance = getRuleDefinition(usingClass, ruleClassProvider);
    for (Class<? extends RuleDefinition> ancestor : instance.getMetadata().ancestors()) {
      if (!visited.containsKey(ancestor)) {
        toVisit.addLast(ancestor);
        visited.put(ancestor, visited.get(usingClass) + 1);
      }
    }
  }

  private RuleDefinition getRuleDefinition(Class<? extends RuleDefinition> usingClass,
      ConfiguredRuleClassProvider ruleClassProvider) {
    if (ruleClassProvider == null) {
      try {
        return usingClass.getConstructor().newInstance();
      } catch (ReflectiveOperationException | IllegalArgumentException e) {
        throw new IllegalStateException(e);
      }
    }
    return ruleClassProvider.getRuleClassDefinition(usingClass.getName());
  }

  private int getAttributeOrderingPriority(RuleDocumentationAttribute attribute) {
    if (DocgenConsts.ATTRIBUTE_ORDERING.containsKey(attribute.attributeName)) {
      return DocgenConsts.ATTRIBUTE_ORDERING.get(attribute.attributeName);
    } else {
      return 0;
    }
  }

  @Override
  public int compareTo(RuleDocumentationAttribute o) {
    int thisPriority = getAttributeOrderingPriority(this);
    int otherPriority = getAttributeOrderingPriority(o);
    if (thisPriority > otherPriority) {
      return 1;
    } else if (thisPriority < otherPriority) {
      return -1;
    } else {
      return this.attributeName.compareTo(o.attributeName);
    }
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof RuleDocumentationAttribute)) {
      return false;
    }
    return attributeName.equals(((RuleDocumentationAttribute) obj).attributeName);
  }

  @Override
  public int hashCode() {
    return attributeName.hashCode();
  }
}
