// 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.collect.ImmutableList;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.docgen.starlark.StarlarkBuiltinDoc;
import com.google.devtools.build.docgen.starlark.StarlarkDocExpander;
import com.google.devtools.build.docgen.starlark.StarlarkMethodDoc;
import com.google.devtools.build.lib.util.Classpath.ClassPathException;
import java.io.File;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import net.starlark.java.annot.StarlarkBuiltin;

/** A class to assemble documentation for Starlark. */
public final class StarlarkDocumentationProcessor {

  private static final ImmutableList<Category> GLOBAL_CATEGORIES =
      ImmutableList.<Category>of(Category.NONE, Category.TOP_LEVEL_TYPE);

  private StarlarkDocumentationProcessor() {}

  /** Generates the Starlark documentation to the given output directory. */
  public static void generateDocumentation(String outputDir, String... args)
      throws IOException, ClassPathException {
    Map<String, String> options = parseOptions(args);

    String docsRoot = options.get("--starlark_docs_root");
    if (docsRoot != null) {
      DocgenConsts.starlarkDocsRoot = docsRoot;
    }

    String linkMapPath = options.get("--link_map_path");
    if (linkMapPath == null) {
      throw new IllegalArgumentException("Required option '--link_map_path' is missing.");
    }

    DocLinkMap linkMap = DocLinkMap.createFromFile(linkMapPath);
    StarlarkDocExpander expander =
        new StarlarkDocExpander(new RuleLinkExpander(/* singlePage= */ false, linkMap));

    Map<String, StarlarkBuiltinDoc> modules =
        new TreeMap<>(StarlarkDocumentationCollector.getAllModules(expander));

    // Generate the top level module first in the doc
    StarlarkBuiltinDoc topLevelModule =
        modules.remove(StarlarkDocumentationCollector.getTopLevelModule().name());
    writePage(outputDir, topLevelModule);

    // Use a LinkedHashMap to preserve ordering of categories, as the output iterates over
    // this map's entry set to determine category ordering.
    Map<Category, List<StarlarkBuiltinDoc>> modulesByCategory = new LinkedHashMap<>();
    for (Category c : Category.values()) {
      modulesByCategory.put(c, new ArrayList<StarlarkBuiltinDoc>());
    }

    modulesByCategory.get(Category.of(topLevelModule.getAnnotation())).add(topLevelModule);

    for (StarlarkBuiltinDoc module : modules.values()) {
      if (module.getAnnotation().documented()) {
        writePage(outputDir, module);
        modulesByCategory.get(Category.of(module.getAnnotation())).add(module);
      }
    }
    Collator us = Collator.getInstance(Locale.US);
    for (List<StarlarkBuiltinDoc> module : modulesByCategory.values()) {
      Collections.sort(module, (doc1, doc2) -> us.compare(doc1.getTitle(), doc2.getTitle()));
    }
    writeCategoryPage(Category.CORE, outputDir, modulesByCategory, expander);
    writeCategoryPage(Category.CONFIGURATION_FRAGMENT, outputDir, modulesByCategory, expander);
    writeCategoryPage(Category.BUILTIN, outputDir, modulesByCategory, expander);
    writeCategoryPage(Category.PROVIDER, outputDir, modulesByCategory, expander);
    writeNavPage(outputDir, modulesByCategory.get(Category.TOP_LEVEL_TYPE));

    // In the code, there are two StarlarkModuleCategory instances that have no heading:
    // TOP_LEVEL_TYPE and NONE.

    // TOP_LEVEL_TYPE also contains the "global" module.
    // We remove both categories and the "global" module from the map and display them manually:
    // - Methods in the "global" module are displayed under "Global Methods and Constants".
    // - Modules in both categories are displayed under "Global Modules" (except for the global
    // module itself).
    List<String> globalFunctions = new ArrayList<>();
    List<String> globalConstants = new ArrayList<>();
    StarlarkBuiltinDoc globalModule = findGlobalModule(modulesByCategory);
    for (StarlarkMethodDoc method : globalModule.getMethods()) {
      if (method.documented()) {
        if (method.isCallable()) {
          globalFunctions.add(method.getName());
        } else {
          globalConstants.add(method.getName());
        }
      }
    }

    List<StarlarkBuiltinDoc> globalModules = new ArrayList<>();
    for (Category globalCategory : GLOBAL_CATEGORIES) {
      for (StarlarkBuiltinDoc module : modulesByCategory.remove(globalCategory)) {
        if (!module.getName().equals(globalModule.getName())) {
          globalModules.add(module);
        }
      }
    }

    Collections.sort(globalModules, (doc1, doc2) -> us.compare(doc1.getName(), doc2.getName()));
    writeOverviewPage(
        outputDir,
        globalModule.getName(),
        globalFunctions,
        globalConstants,
        globalModules,
        modulesByCategory);
    if (shouldCreateToc(options)) {
      writeTableOfContents(outputDir, globalModules, modulesByCategory);
    }
  }

  private static StarlarkBuiltinDoc findGlobalModule(
      Map<Category, List<StarlarkBuiltinDoc>> modulesByCategory) {
    List<StarlarkBuiltinDoc> topLevelModules = modulesByCategory.get(Category.TOP_LEVEL_TYPE);
    String globalModuleName = StarlarkDocumentationCollector.getTopLevelModule().name();
    for (StarlarkBuiltinDoc module : topLevelModules) {
      if (module.getName().equals(globalModuleName)) {
        return module;
      }
    }

    throw new IllegalStateException("No globals module in the top level category.");
  }

  private static void writePage(String outputDir, StarlarkBuiltinDoc module) throws IOException {
    File starlarkDocPath = new File(outputDir + "/" + module.getName() + ".html");
    Page page = TemplateEngine.newPage(DocgenConsts.STARLARK_LIBRARY_TEMPLATE);
    page.add("module", module);
    page.write(starlarkDocPath);
  }

  private static void writeCategoryPage(
      Category category,
      String outputDir,
      Map<Category, List<StarlarkBuiltinDoc>> modules,
      StarlarkDocExpander expander)
      throws IOException {
    File starlarkDocPath =
        new File(String.format("%s/starlark-%s.html", outputDir, category.getTemplateIdentifier()));
    Page page = TemplateEngine.newPage(DocgenConsts.STARLARK_MODULE_CATEGORY_TEMPLATE);
    page.add("category", category);
    page.add("modules", modules.get(category));
    page.add("description", expander.expand(category.description));
    page.write(starlarkDocPath);
  }

  private static void writeNavPage(String outputDir, List<StarlarkBuiltinDoc> navModules)
      throws IOException {
    File navFile = new File(outputDir + "/starlark-nav.html");
    Page page = TemplateEngine.newPage(DocgenConsts.STARLARK_NAV_TEMPLATE);
    page.add("modules", navModules);
    page.write(navFile);
  }

  private static void writeOverviewPage(
      String outputDir,
      String globalModuleName,
      List<String> globalFunctions,
      List<String> globalConstants,
      List<StarlarkBuiltinDoc> globalModules,
      Map<Category, List<StarlarkBuiltinDoc>> modulesPerCategory)
      throws IOException {
    File starlarkDocPath = new File(outputDir + "/starlark-overview.html");
    Page page = TemplateEngine.newPage(DocgenConsts.STARLARK_OVERVIEW_TEMPLATE);
    page.add("global_name", globalModuleName);
    page.add("global_functions", globalFunctions);
    page.add("global_constants", globalConstants);
    page.add("global_modules", globalModules);
    page.add("modules", modulesPerCategory);
    page.write(starlarkDocPath);
  }

  private static void writeTableOfContents(
      String outputDir,
      List<StarlarkBuiltinDoc> globalModules,
      Map<Category, List<StarlarkBuiltinDoc>> modulesPerCategory)
      throws IOException {
    File starlarkDocPath = new File(outputDir + "/_toc.yaml");
    Page page = TemplateEngine.newPage(DocgenConsts.STARLARK_TOC_TEMPLATE);
    page.add("global_modules", globalModules);
    page.add("modules", modulesPerCategory);
    page.write(starlarkDocPath);
  }

  private static Map<String, String> parseOptions(String... args) {
    Map<String, String> options = new HashMap<>();
    for (String arg : args) {
      if (arg.startsWith("--")) {
        String[] parts = arg.split("=", 2);
        options.put(parts[0], parts.length > 1 ? parts[1] : null);
      }
    }
    return options;
  }

  private static boolean shouldCreateToc(Map<String, String> options) {
    String arg = options.get("--create_toc");
    if (arg == null) {
      return false;
    }
    return Boolean.parseBoolean(arg) || arg.equals("1");
  }

  /**
   * An enumeration of categories used to organize the API index. Instances of this class are
   * accessed by templates, using reflection.
   */
  public enum Category {
    CONFIGURATION_FRAGMENT(
        "Configuration Fragments",
        "Configuration fragments give rules access to "
            + "language-specific parts of <a href=\"configuration.html\">"
            + "configuration</a>. "
            + "<p>Rule implementations can get them using "
            + "<code><a href=\"ctx.html#fragments\">ctx."
            + "fragments</a>.<i>[fragment name]</i></code>"),

    PROVIDER(
        "Providers",
        "This section lists providers available on built-in rules. See the <a"
            + " href='https://bazel.build/extending/rules#providers'>Rules page</a> for more on"
            + " providers."),

    BUILTIN("Built-in Types", "This section lists types of Starlark objects."),

    // Used for top-level modules of functions in the global namespace. Such modules will always
    // be usable solely by accessing their members, via modulename.funcname() or
    // modulename.constantname.
    // Examples: attr, cc_common, config, java_common
    TOP_LEVEL_TYPE(null, null),

    CORE(
        "Core Starlark data types",
        "This section lists the data types of the <a"
            + " href='https://github.com/bazelbuild/starlark/blob/master/spec.md#built-in-constants-and-functions'>Starlark"
            + " core language</a>."),

    // Legacy uncategorized type; these are treated like TOP_LEVEL_TYPE in documentation.
    NONE(null, null);

    // Maps (essentially free-form) strings in annotations to permitted categories.
    static Category of(StarlarkBuiltin annot) {
      switch (annot.category()) {
        case DocCategory.CONFIGURATION_FRAGMENT:
          return CONFIGURATION_FRAGMENT;
        case DocCategory.PROVIDER:
          return PROVIDER;
        case DocCategory.BUILTIN:
          return BUILTIN;
        case DocCategory.TOP_LEVEL_TYPE:
          return TOP_LEVEL_TYPE;
        case DocCategory.NONE:
          return NONE;
        case "core": // interpreter built-ins (e.g. int)
        case "core.lib": // Starlark standard modules (e.g. json)
          return CORE;
        case "": // no annotation
          return TOP_LEVEL_TYPE;
        default:
          throw new IllegalStateException(
              String.format(
                  "docgen does not recognize DocCategory '%s' for StarlarkBuiltin '%s'",
                  annot.category(), annot.name()));
      }
    }

    private Category(String title, String description) {
      this.title = title;
      this.description = description;
    }

    private final String title;
    private final String description;

    public String getTitle() {
      return title;
    }

    public String getDescription() {
      return description;
    }

    public String getTemplateIdentifier() {
      return name().toLowerCase().replace("_", "-");
    }
  }
}
