//===-- HTMLGenerator.cpp - HTML Generator ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Generators.h"
#include "Representation.h"
#include "clang/Basic/Version.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <string>

using namespace llvm;

namespace clang {
namespace doc {

namespace {

class HTMLTag {
public:
  // Any other tag can be added if required
  enum TagType {
    TAG_A,
    TAG_DIV,
    TAG_FOOTER,
    TAG_H1,
    TAG_H2,
    TAG_H3,
    TAG_HEADER,
    TAG_LI,
    TAG_LINK,
    TAG_MAIN,
    TAG_META,
    TAG_OL,
    TAG_P,
    TAG_SCRIPT,
    TAG_SPAN,
    TAG_TITLE,
    TAG_UL,
  };

  HTMLTag() = default;
  constexpr HTMLTag(TagType Value) : Value(Value) {}

  operator TagType() const { return Value; }
  operator bool() = delete;

  bool IsSelfClosing() const;
  llvm::SmallString<16> ToString() const;

private:
  TagType Value;
};

enum NodeType {
  NODE_TEXT,
  NODE_TAG,
};

struct HTMLNode {
  HTMLNode(NodeType Type) : Type(Type) {}
  virtual ~HTMLNode() = default;

  virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
  NodeType Type; // Type of node
};

struct TextNode : public HTMLNode {
  TextNode(const Twine &Text)
      : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()) {}

  std::string Text; // Content of node
  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
};

struct TagNode : public HTMLNode {
  TagNode(HTMLTag Tag) : HTMLNode(NodeType::NODE_TAG), Tag(Tag) {}
  TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
    Children.emplace_back(std::make_unique<TextNode>(Text.str()));
  }

  HTMLTag Tag; // Name of HTML Tag (p, div, h1)
  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
  std::vector<std::pair<std::string, std::string>>
      Attributes; // List of key-value attributes for tag

  void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
};

constexpr const char *kDoctypeDecl = "<!DOCTYPE html>";

struct HTMLFile {
  std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
  void Render(llvm::raw_ostream &OS) {
    OS << kDoctypeDecl << "\n";
    for (const auto &C : Children) {
      C->Render(OS, 0);
      OS << "\n";
    }
  }
};

} // namespace

bool HTMLTag::IsSelfClosing() const {
  switch (Value) {
  case HTMLTag::TAG_META:
  case HTMLTag::TAG_LINK:
    return true;
  case HTMLTag::TAG_A:
  case HTMLTag::TAG_DIV:
  case HTMLTag::TAG_FOOTER:
  case HTMLTag::TAG_H1:
  case HTMLTag::TAG_H2:
  case HTMLTag::TAG_H3:
  case HTMLTag::TAG_HEADER:
  case HTMLTag::TAG_LI:
  case HTMLTag::TAG_MAIN:
  case HTMLTag::TAG_OL:
  case HTMLTag::TAG_P:
  case HTMLTag::TAG_SCRIPT:
  case HTMLTag::TAG_SPAN:
  case HTMLTag::TAG_TITLE:
  case HTMLTag::TAG_UL:
    return false;
  }
  llvm_unreachable("Unhandled HTMLTag::TagType");
}

llvm::SmallString<16> HTMLTag::ToString() const {
  switch (Value) {
  case HTMLTag::TAG_A:
    return llvm::SmallString<16>("a");
  case HTMLTag::TAG_DIV:
    return llvm::SmallString<16>("div");
  case HTMLTag::TAG_FOOTER:
    return llvm::SmallString<16>("footer");
  case HTMLTag::TAG_H1:
    return llvm::SmallString<16>("h1");
  case HTMLTag::TAG_H2:
    return llvm::SmallString<16>("h2");
  case HTMLTag::TAG_H3:
    return llvm::SmallString<16>("h3");
  case HTMLTag::TAG_HEADER:
    return llvm::SmallString<16>("header");
  case HTMLTag::TAG_LI:
    return llvm::SmallString<16>("li");
  case HTMLTag::TAG_LINK:
    return llvm::SmallString<16>("link");
  case HTMLTag::TAG_MAIN:
    return llvm::SmallString<16>("main");
  case HTMLTag::TAG_META:
    return llvm::SmallString<16>("meta");
  case HTMLTag::TAG_OL:
    return llvm::SmallString<16>("ol");
  case HTMLTag::TAG_P:
    return llvm::SmallString<16>("p");
  case HTMLTag::TAG_SCRIPT:
    return llvm::SmallString<16>("script");
  case HTMLTag::TAG_SPAN:
    return llvm::SmallString<16>("span");
  case HTMLTag::TAG_TITLE:
    return llvm::SmallString<16>("title");
  case HTMLTag::TAG_UL:
    return llvm::SmallString<16>("ul");
  }
  llvm_unreachable("Unhandled HTMLTag::TagType");
}

void TextNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
  OS.indent(IndentationLevel * 2);
  printHTMLEscaped(Text, OS);
}

void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) {
  // Children nodes are rendered in the same line if all of them are text nodes
  bool InlineChildren = true;
  for (const auto &C : Children)
    if (C->Type == NodeType::NODE_TAG) {
      InlineChildren = false;
      break;
    }
  OS.indent(IndentationLevel * 2);
  OS << "<" << Tag.ToString();
  for (const auto &A : Attributes)
    OS << " " << A.first << "=\"" << A.second << "\"";
  if (Tag.IsSelfClosing()) {
    OS << "/>";
    return;
  }
  OS << ">";
  if (!InlineChildren)
    OS << "\n";
  bool NewLineRendered = true;
  for (const auto &C : Children) {
    int ChildrenIndentation =
        InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
    C->Render(OS, ChildrenIndentation);
    if (!InlineChildren && (C == Children.back() ||
                            (C->Type != NodeType::NODE_TEXT ||
                             (&C + 1)->get()->Type != NodeType::NODE_TEXT))) {
      OS << "\n";
      NewLineRendered = true;
    } else
      NewLineRendered = false;
  }
  if (!InlineChildren)
    OS.indent(IndentationLevel * 2);
  OS << "</" << Tag.ToString() << ">";
}

template <typename Derived, typename Base,
          typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
static void AppendVector(std::vector<Derived> &&New,
                         std::vector<Base> &Original) {
  std::move(New.begin(), New.end(), std::back_inserter(Original));
}

// Compute the relative path from an Origin directory to a Destination directory
static SmallString<128> computeRelativePath(StringRef Destination,
                                            StringRef Origin) {
  // If Origin is empty, the relative path to the Destination is its complete
  // path.
  if (Origin.empty())
    return Destination;

  // The relative path is an empty path if both directories are the same.
  if (Destination == Origin)
    return {};

  // These iterators iterate through each of their parent directories
  llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(Destination);
  llvm::sys::path::const_iterator FileE = llvm::sys::path::end(Destination);
  llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(Origin);
  llvm::sys::path::const_iterator DirE = llvm::sys::path::end(Origin);
  // Advance both iterators until the paths differ. Example:
  //    Destination = A/B/C/D
  //    Origin      = A/B/E/F
  // FileI will point to C and DirI to E. The directories behind them is the
  // directory they share (A/B).
  while (FileI != FileE && DirI != DirE && *FileI == *DirI) {
    ++FileI;
    ++DirI;
  }
  SmallString<128> Result; // This will hold the resulting path.
  // Result has to go up one directory for each of the remaining directories in
  // Origin
  while (DirI != DirE) {
    llvm::sys::path::append(Result, "..");
    ++DirI;
  }
  // Result has to append each of the remaining directories in Destination
  while (FileI != FileE) {
    llvm::sys::path::append(Result, *FileI);
    ++FileI;
  }
  return Result;
}

// HTML generation

static std::vector<std::unique_ptr<TagNode>>
genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
  std::vector<std::unique_ptr<TagNode>> Out;
  for (const auto &FilePath : CDCtx.UserStylesheets) {
    auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK);
    LinkNode->Attributes.emplace_back("rel", "stylesheet");
    SmallString<128> StylesheetPath = computeRelativePath("", InfoPath);
    llvm::sys::path::append(StylesheetPath,
                            llvm::sys::path::filename(FilePath));
    // Paths in HTML must be in posix-style
    llvm::sys::path::native(StylesheetPath, llvm::sys::path::Style::posix);
    LinkNode->Attributes.emplace_back("href", std::string(StylesheetPath.str()));
    Out.emplace_back(std::move(LinkNode));
  }
  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
  std::vector<std::unique_ptr<TagNode>> Out;
  for (const auto &FilePath : CDCtx.JsScripts) {
    auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
    SmallString<128> ScriptPath = computeRelativePath("", InfoPath);
    llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
    // Paths in HTML must be in posix-style
    llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix);
    ScriptNode->Attributes.emplace_back("src", std::string(ScriptPath.str()));
    Out.emplace_back(std::move(ScriptNode));
  }
  return Out;
}

static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
  auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_A, Text);
  LinkNode->Attributes.emplace_back("href", Link.str());
  return LinkNode;
}

static std::unique_ptr<HTMLNode>
genReference(const Reference &Type, StringRef CurrentDirectory,
             llvm::Optional<StringRef> JumpToSection = None) {
  if (Type.Path.empty() && !Type.IsInGlobalNamespace) {
    if (!JumpToSection)
      return std::make_unique<TextNode>(Type.Name);
    else
      return genLink(Type.Name, "#" + JumpToSection.getValue());
  }
  llvm::SmallString<64> Path = Type.getRelativeFilePath(CurrentDirectory);
  llvm::sys::path::append(Path, Type.getFileBaseName() + ".html");

  // Paths in HTML must be in posix-style
  llvm::sys::path::native(Path, llvm::sys::path::Style::posix);
  if (JumpToSection)
    Path += ("#" + JumpToSection.getValue()).str();
  return genLink(Type.Name, Path);
}

static std::vector<std::unique_ptr<HTMLNode>>
genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs,
                 const StringRef &CurrentDirectory) {
  std::vector<std::unique_ptr<HTMLNode>> Out;
  for (const auto &R : Refs) {
    if (&R != Refs.begin())
      Out.emplace_back(std::make_unique<TextNode>(", "));
    Out.emplace_back(genReference(R, CurrentDirectory));
  }
  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const EnumInfo &I, const ClangDocContext &CDCtx);
static std::vector<std::unique_ptr<TagNode>>
genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
        StringRef ParentInfoDir);

static std::vector<std::unique_ptr<TagNode>>
genEnumsBlock(const std::vector<EnumInfo> &Enums,
              const ClangDocContext &CDCtx) {
  if (Enums.empty())
    return {};

  std::vector<std::unique_ptr<TagNode>> Out;
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
  Out.back()->Attributes.emplace_back("id", "Enums");
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
  auto &DivBody = Out.back();
  for (const auto &E : Enums) {
    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E, CDCtx);
    AppendVector(std::move(Nodes), DivBody->Children);
  }
  return Out;
}

static std::unique_ptr<TagNode>
genEnumMembersBlock(const llvm::SmallVector<SmallString<16>, 4> &Members) {
  if (Members.empty())
    return nullptr;

  auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL);
  for (const auto &M : Members)
    List->Children.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_LI, M));
  return List;
}

static std::vector<std::unique_ptr<TagNode>>
genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
                  const ClangDocContext &CDCtx, StringRef ParentInfoDir) {
  if (Functions.empty())
    return {};

  std::vector<std::unique_ptr<TagNode>> Out;
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
  Out.back()->Attributes.emplace_back("id", "Functions");
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
  auto &DivBody = Out.back();
  for (const auto &F : Functions) {
    std::vector<std::unique_ptr<TagNode>> Nodes =
        genHTML(F, CDCtx, ParentInfoDir);
    AppendVector(std::move(Nodes), DivBody->Children);
  }
  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
                      StringRef ParentInfoDir) {
  if (Members.empty())
    return {};

  std::vector<std::unique_ptr<TagNode>> Out;
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
  Out.back()->Attributes.emplace_back("id", "Members");
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
  auto &ULBody = Out.back();
  for (const auto &M : Members) {
    std::string Access = getAccessSpelling(M.Access).str();
    if (Access != "")
      Access = Access + " ";
    auto LIBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
    LIBody->Children.emplace_back(std::make_unique<TextNode>(Access));
    LIBody->Children.emplace_back(genReference(M.Type, ParentInfoDir));
    LIBody->Children.emplace_back(std::make_unique<TextNode>(" " + M.Name));
    ULBody->Children.emplace_back(std::move(LIBody));
  }
  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genReferencesBlock(const std::vector<Reference> &References,
                   llvm::StringRef Title, StringRef ParentPath) {
  if (References.empty())
    return {};

  std::vector<std::unique_ptr<TagNode>> Out;
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
  Out.back()->Attributes.emplace_back("id", std::string(Title));
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
  auto &ULBody = Out.back();
  for (const auto &R : References) {
    auto LiNode = std::make_unique<TagNode>(HTMLTag::TAG_LI);
    LiNode->Children.emplace_back(genReference(R, ParentPath));
    ULBody->Children.emplace_back(std::move(LiNode));
  }
  return Out;
}

static std::unique_ptr<TagNode>
writeFileDefinition(const Location &L,
                    llvm::Optional<StringRef> RepositoryUrl = None) {
  if (!L.IsFileInRootDir || !RepositoryUrl)
    return std::make_unique<TagNode>(
        HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) +
                            " of file " + L.Filename);
  SmallString<128> FileURL(RepositoryUrl.getValue());
  llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);
  auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P);
  Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line "));
  auto LocNumberNode =
      std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
  // The links to a specific line in the source code use the github /
  // googlesource notation so it won't work for all hosting pages.
  LocNumberNode->Attributes.emplace_back(
      "href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
  Node->Children.emplace_back(std::move(LocNumberNode));
  Node->Children.emplace_back(std::make_unique<TextNode>(" of file "));
  auto LocFileNode = std::make_unique<TagNode>(
      HTMLTag::TAG_A, llvm::sys::path::filename(FileURL));
  LocFileNode->Attributes.emplace_back("href", std::string(FileURL.str()));
  Node->Children.emplace_back(std::move(LocFileNode));
  return Node;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList);

// Generates a list of child nodes for the HTML head tag
// It contains a meta node, link nodes to import CSS files, and script nodes to
// import JS files
static std::vector<std::unique_ptr<TagNode>>
genFileHeadNodes(StringRef Title, StringRef InfoPath,
                 const ClangDocContext &CDCtx) {
  std::vector<std::unique_ptr<TagNode>> Out;
  auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META);
  MetaNode->Attributes.emplace_back("charset", "utf-8");
  Out.emplace_back(std::move(MetaNode));
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title));
  std::vector<std::unique_ptr<TagNode>> StylesheetsNodes =
      genStylesheetsHTML(InfoPath, CDCtx);
  AppendVector(std::move(StylesheetsNodes), Out);
  std::vector<std::unique_ptr<TagNode>> JsNodes =
      genJsScriptsHTML(InfoPath, CDCtx);
  AppendVector(std::move(JsNodes), Out);
  return Out;
}

// Generates a header HTML node that can be used for any file
// It contains the project name
static std::unique_ptr<TagNode> genFileHeaderNode(StringRef ProjectName) {
  auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER, ProjectName);
  HeaderNode->Attributes.emplace_back("id", "project-title");
  return HeaderNode;
}

// Generates a main HTML node that has all the main content of an info file
// It contains both indexes and the info's documented information
// This function should only be used for the info files (not for the file that
// only has the general index)
static std::unique_ptr<TagNode> genInfoFileMainNode(
    StringRef InfoPath,
    std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
    const Index &InfoIndex) {
  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);

  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
  LeftSidebarNode->Attributes.emplace_back("path", std::string(InfoPath));
  LeftSidebarNode->Attributes.emplace_back(
      "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");

  auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
  MainContentNode->Attributes.emplace_back("id", "main-content");
  MainContentNode->Attributes.emplace_back(
      "class", "col-xs-12 col-sm-9 col-md-8 main-content");
  AppendVector(std::move(MainContentInnerNodes), MainContentNode->Children);

  auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
  RightSidebarNode->Attributes.emplace_back("id", "sidebar-right");
  RightSidebarNode->Attributes.emplace_back(
      "class", "col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right");
  std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
      genHTML(InfoIndex, InfoPath, true);
  AppendVector(std::move(InfoIndexHTML), RightSidebarNode->Children);

  MainNode->Children.emplace_back(std::move(LeftSidebarNode));
  MainNode->Children.emplace_back(std::move(MainContentNode));
  MainNode->Children.emplace_back(std::move(RightSidebarNode));

  return MainNode;
}

// Generates a footer HTML node that can be used for any file
// It contains clang-doc's version
static std::unique_ptr<TagNode> genFileFooterNode() {
  auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER);
  auto SpanNode = std::make_unique<TagNode>(
      HTMLTag::TAG_SPAN, clang::getClangToolFullVersion("clang-doc"));
  SpanNode->Attributes.emplace_back("class", "no-break");
  FooterNode->Children.emplace_back(std::move(SpanNode));
  return FooterNode;
}

// Generates a complete HTMLFile for an Info
static HTMLFile
genInfoFile(StringRef Title, StringRef InfoPath,
            std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
            const Index &InfoIndex, const ClangDocContext &CDCtx) {
  HTMLFile F;

  std::vector<std::unique_ptr<TagNode>> HeadNodes =
      genFileHeadNodes(Title, InfoPath, CDCtx);
  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
  std::unique_ptr<TagNode> MainNode =
      genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex);
  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();

  AppendVector(std::move(HeadNodes), F.Children);
  F.Children.emplace_back(std::move(HeaderNode));
  F.Children.emplace_back(std::move(MainNode));
  F.Children.emplace_back(std::move(FooterNode));

  return F;
}

template <typename T,
          typename = std::enable_if<std::is_base_of<T, Info>::value>>
static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) {
  Index Idx(Title, Title);
  for (const auto &C : Infos)
    Idx.Children.emplace_back(C.extractName(),
                              llvm::toHex(llvm::toStringRef(C.USR)));
  return Idx;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) {
  std::vector<std::unique_ptr<TagNode>> Out;
  if (!Index.Name.empty()) {
    Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN));
    auto &SpanBody = Out.back();
    if (!Index.JumpToSection)
      SpanBody->Children.emplace_back(genReference(Index, InfoPath));
    else
      SpanBody->Children.emplace_back(genReference(
          Index, InfoPath, StringRef{Index.JumpToSection.getValue()}));
  }
  if (Index.Children.empty())
    return Out;
  // Only the outermost list should use ol, the others should use ul
  HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL;
  Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag));
  const auto &UlBody = Out.back();
  for (const auto &C : Index.Children) {
    auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath, false);
    AppendVector(std::move(Nodes), LiBody->Children);
    UlBody->Children.emplace_back(std::move(LiBody));
  }
  return Out;
}

static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) {
  if (I.Kind == "FullComment") {
    auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
    for (const auto &Child : I.Children) {
      std::unique_ptr<HTMLNode> Node = genHTML(*Child);
      if (Node)
        FullComment->Children.emplace_back(std::move(Node));
    }
    return std::move(FullComment);
  } else if (I.Kind == "ParagraphComment") {
    auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P);
    for (const auto &Child : I.Children) {
      std::unique_ptr<HTMLNode> Node = genHTML(*Child);
      if (Node)
        ParagraphComment->Children.emplace_back(std::move(Node));
    }
    if (ParagraphComment->Children.empty())
      return nullptr;
    return std::move(ParagraphComment);
  } else if (I.Kind == "TextComment") {
    if (I.Text == "")
      return nullptr;
    return std::make_unique<TextNode>(I.Text);
  }
  return nullptr;
}

static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) {
  auto CommentBlock = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
  for (const auto &Child : C) {
    if (std::unique_ptr<HTMLNode> Node = genHTML(Child))
      CommentBlock->Children.emplace_back(std::move(Node));
  }
  return CommentBlock;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) {
  std::vector<std::unique_ptr<TagNode>> Out;
  std::string EnumType;
  if (I.Scoped)
    EnumType = "enum class ";
  else
    EnumType = "enum ";

  Out.emplace_back(
      std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
  Out.back()->Attributes.emplace_back("id",
                                      llvm::toHex(llvm::toStringRef(I.USR)));

  std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
  if (Node)
    Out.emplace_back(std::move(Node));

  if (I.DefLoc) {
    if (!CDCtx.RepositoryUrl)
      Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
    else
      Out.emplace_back(writeFileDefinition(
          I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
  }

  std::string Description;
  if (!I.Description.empty())
    Out.emplace_back(genHTML(I.Description));

  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
        StringRef ParentInfoDir) {
  std::vector<std::unique_ptr<TagNode>> Out;
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
  // USR is used as id for functions instead of name to disambiguate function
  // overloads.
  Out.back()->Attributes.emplace_back("id",
                                      llvm::toHex(llvm::toStringRef(I.USR)));

  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
  auto &FunctionHeader = Out.back();

  std::string Access = getAccessSpelling(I.Access).str();
  if (Access != "")
    FunctionHeader->Children.emplace_back(
        std::make_unique<TextNode>(Access + " "));
  if (I.ReturnType.Type.Name != "") {
    FunctionHeader->Children.emplace_back(
        genReference(I.ReturnType.Type, ParentInfoDir));
    FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(" "));
  }
  FunctionHeader->Children.emplace_back(
      std::make_unique<TextNode>(I.Name + "("));

  for (const auto &P : I.Params) {
    if (&P != I.Params.begin())
      FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(", "));
    FunctionHeader->Children.emplace_back(genReference(P.Type, ParentInfoDir));
    FunctionHeader->Children.emplace_back(
        std::make_unique<TextNode>(" " + P.Name));
  }
  FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(")"));

  if (I.DefLoc) {
    if (!CDCtx.RepositoryUrl)
      Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
    else
      Out.emplace_back(writeFileDefinition(
          I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
  }

  std::string Description;
  if (!I.Description.empty())
    Out.emplace_back(genHTML(I.Description));

  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const NamespaceInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
        std::string &InfoTitle) {
  std::vector<std::unique_ptr<TagNode>> Out;
  if (I.Name.str() == "")
    InfoTitle = "Global Namespace";
  else
    InfoTitle = ("namespace " + I.Name).str();

  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));

  std::string Description;
  if (!I.Description.empty())
    Out.emplace_back(genHTML(I.Description));

  llvm::SmallString<64> BasePath = I.getRelativeFilePath("");

  std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
      genReferencesBlock(I.ChildNamespaces, "Namespaces", BasePath);
  AppendVector(std::move(ChildNamespaces), Out);
  std::vector<std::unique_ptr<TagNode>> ChildRecords =
      genReferencesBlock(I.ChildRecords, "Records", BasePath);
  AppendVector(std::move(ChildRecords), Out);

  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
      genFunctionsBlock(I.ChildFunctions, CDCtx, BasePath);
  AppendVector(std::move(ChildFunctions), Out);
  std::vector<std::unique_ptr<TagNode>> ChildEnums =
      genEnumsBlock(I.ChildEnums, CDCtx);
  AppendVector(std::move(ChildEnums), Out);

  if (!I.ChildNamespaces.empty())
    InfoIndex.Children.emplace_back("Namespaces", "Namespaces");
  if (!I.ChildRecords.empty())
    InfoIndex.Children.emplace_back("Records", "Records");
  if (!I.ChildFunctions.empty())
    InfoIndex.Children.emplace_back(
        genInfoIndexItem(I.ChildFunctions, "Functions"));
  if (!I.ChildEnums.empty())
    InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));

  return Out;
}

static std::vector<std::unique_ptr<TagNode>>
genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx,
        std::string &InfoTitle) {
  std::vector<std::unique_ptr<TagNode>> Out;
  InfoTitle = (getTagType(I.TagType) + " " + I.Name).str();
  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));

  if (I.DefLoc) {
    if (!CDCtx.RepositoryUrl)
      Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
    else
      Out.emplace_back(writeFileDefinition(
          I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
  }

  std::string Description;
  if (!I.Description.empty())
    Out.emplace_back(genHTML(I.Description));

  std::vector<std::unique_ptr<HTMLNode>> Parents =
      genReferenceList(I.Parents, I.Path);
  std::vector<std::unique_ptr<HTMLNode>> VParents =
      genReferenceList(I.VirtualParents, I.Path);
  if (!Parents.empty() || !VParents.empty()) {
    Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
    auto &PBody = Out.back();
    PBody->Children.emplace_back(std::make_unique<TextNode>("Inherits from "));
    if (Parents.empty())
      AppendVector(std::move(VParents), PBody->Children);
    else if (VParents.empty())
      AppendVector(std::move(Parents), PBody->Children);
    else {
      AppendVector(std::move(Parents), PBody->Children);
      PBody->Children.emplace_back(std::make_unique<TextNode>(", "));
      AppendVector(std::move(VParents), PBody->Children);
    }
  }

  std::vector<std::unique_ptr<TagNode>> Members =
      genRecordMembersBlock(I.Members, I.Path);
  AppendVector(std::move(Members), Out);
  std::vector<std::unique_ptr<TagNode>> ChildRecords =
      genReferencesBlock(I.ChildRecords, "Records", I.Path);
  AppendVector(std::move(ChildRecords), Out);

  std::vector<std::unique_ptr<TagNode>> ChildFunctions =
      genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path);
  AppendVector(std::move(ChildFunctions), Out);
  std::vector<std::unique_ptr<TagNode>> ChildEnums =
      genEnumsBlock(I.ChildEnums, CDCtx);
  AppendVector(std::move(ChildEnums), Out);

  if (!I.Members.empty())
    InfoIndex.Children.emplace_back("Members", "Members");
  if (!I.ChildRecords.empty())
    InfoIndex.Children.emplace_back("Records", "Records");
  if (!I.ChildFunctions.empty())
    InfoIndex.Children.emplace_back(
        genInfoIndexItem(I.ChildFunctions, "Functions"));
  if (!I.ChildEnums.empty())
    InfoIndex.Children.emplace_back(genInfoIndexItem(I.ChildEnums, "Enums"));

  return Out;
}

/// Generator for HTML documentation.
class HTMLGenerator : public Generator {
public:
  static const char *Format;

  llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
                                 const ClangDocContext &CDCtx) override;
  llvm::Error createResources(ClangDocContext &CDCtx) override;
};

const char *HTMLGenerator::Format = "html";

llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
                                              const ClangDocContext &CDCtx) {
  std::string InfoTitle;
  std::vector<std::unique_ptr<TagNode>> MainContentNodes;
  Index InfoIndex;
  switch (I->IT) {
  case InfoType::IT_namespace:
    MainContentNodes = genHTML(*static_cast<clang::doc::NamespaceInfo *>(I),
                               InfoIndex, CDCtx, InfoTitle);
    break;
  case InfoType::IT_record:
    MainContentNodes = genHTML(*static_cast<clang::doc::RecordInfo *>(I),
                               InfoIndex, CDCtx, InfoTitle);
    break;
  case InfoType::IT_enum:
    MainContentNodes = genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
    break;
  case InfoType::IT_function:
    MainContentNodes =
        genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, "");
    break;
  case InfoType::IT_default:
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "unexpected info type");
  }

  HTMLFile F = genInfoFile(InfoTitle, I->getRelativeFilePath(""),
                           MainContentNodes, InfoIndex, CDCtx);
  F.Render(OS);

  return llvm::Error::success();
}

static std::string getRefType(InfoType IT) {
  switch (IT) {
  case InfoType::IT_default:
    return "default";
  case InfoType::IT_namespace:
    return "namespace";
  case InfoType::IT_record:
    return "record";
  case InfoType::IT_function:
    return "function";
  case InfoType::IT_enum:
    return "enum";
  }
  llvm_unreachable("Unknown InfoType");
}

static llvm::Error SerializeIndex(ClangDocContext &CDCtx) {
  std::error_code OK;
  std::error_code FileErr;
  llvm::SmallString<128> FilePath;
  llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
  llvm::sys::path::append(FilePath, "index_json.js");
  llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
  if (FileErr != OK) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "error creating index file: " +
                                       FileErr.message());
  }
  CDCtx.Idx.sort();
  llvm::json::OStream J(OS, 2);
  std::function<void(Index)> IndexToJSON = [&](Index I) {
    J.object([&] {
      J.attribute("USR", toHex(llvm::toStringRef(I.USR)));
      J.attribute("Name", I.Name);
      J.attribute("RefType", getRefType(I.RefType));
      J.attribute("Path", I.getRelativeFilePath(""));
      J.attributeArray("Children", [&] {
        for (const Index &C : I.Children)
          IndexToJSON(C);
      });
    });
  };
  OS << "var JsonIndex = `\n";
  IndexToJSON(CDCtx.Idx);
  OS << "`;\n";
  return llvm::Error::success();
}

// Generates a main HTML node that has the main content of the file that shows
// only the general index
// It contains the general index with links to all the generated files
static std::unique_ptr<TagNode> genIndexFileMainNode() {
  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);

  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
  LeftSidebarNode->Attributes.emplace_back("path", "");
  LeftSidebarNode->Attributes.emplace_back(
      "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
  LeftSidebarNode->Attributes.emplace_back("style", "flex: 0 100%;");

  MainNode->Children.emplace_back(std::move(LeftSidebarNode));

  return MainNode;
}

static llvm::Error GenIndex(const ClangDocContext &CDCtx) {
  std::error_code FileErr, OK;
  llvm::SmallString<128> IndexPath;
  llvm::sys::path::native(CDCtx.OutDirectory, IndexPath);
  llvm::sys::path::append(IndexPath, "index.html");
  llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
  if (FileErr != OK) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "error creating main index: " +
                                       FileErr.message());
  }

  HTMLFile F;

  std::vector<std::unique_ptr<TagNode>> HeadNodes =
      genFileHeadNodes("Index", "", CDCtx);
  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
  std::unique_ptr<TagNode> MainNode = genIndexFileMainNode();
  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();

  AppendVector(std::move(HeadNodes), F.Children);
  F.Children.emplace_back(std::move(HeaderNode));
  F.Children.emplace_back(std::move(MainNode));
  F.Children.emplace_back(std::move(FooterNode));

  F.Render(IndexOS);

  return llvm::Error::success();
}

static llvm::Error CopyFile(StringRef FilePath, StringRef OutDirectory) {
  llvm::SmallString<128> PathWrite;
  llvm::sys::path::native(OutDirectory, PathWrite);
  llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath));
  llvm::SmallString<128> PathRead;
  llvm::sys::path::native(FilePath, PathRead);
  std::error_code OK;
  std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);
  if (FileErr != OK) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "error creating file " +
                                       llvm::sys::path::filename(FilePath) +
                                       ": " + FileErr.message() + "\n");
  }
  return llvm::Error::success();
}

llvm::Error HTMLGenerator::createResources(ClangDocContext &CDCtx) {
  auto Err = SerializeIndex(CDCtx);
  if (Err)
    return Err;
  Err = GenIndex(CDCtx);
  if (Err)
    return Err;

  for (const auto &FilePath : CDCtx.UserStylesheets) {
    Err = CopyFile(FilePath, CDCtx.OutDirectory);
    if (Err)
      return Err;
  }
  for (const auto &FilePath : CDCtx.FilesToCopy) {
    Err = CopyFile(FilePath, CDCtx.OutDirectory);
    if (Err)
      return Err;
  }
  return llvm::Error::success();
}

static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format,
                                                  "Generator for HTML output.");

// This anchor is used to force the linker to link in the generated object
// file and thus register the generator.
volatile int HTMLGeneratorAnchorSource = 0;

} // namespace doc
} // namespace clang
