(function () {
  "use strict";

  var content = document.querySelector(".content");
  var nav = document.querySelector(".nav");

  function buildPageNavigation() {
    if (!content || !nav || !window.HELP_SEARCH_INDEX) {
      return;
    }

    var headings = Array.prototype.slice.call(content.querySelectorAll("h2"));
    headings.forEach(function (heading, index) {
      heading.id = heading.id || "section-" + (index + 1);
    });

    Array.prototype.slice.call(nav.children).forEach(function (pageLink) {
      if (pageLink.tagName !== "A") {
        return;
      }

      var page = pageLink.getAttribute("href").split(/[?#]/)[0];
      var sections = window.HELP_SEARCH_INDEX.filter(function (entry) {
        return entry.page === page;
      });
      if (!sections.length) {
        return;
      }

      var isCurrent = pageLink.getAttribute("aria-current") === "page";
      var details = document.createElement("details");
      details.className = "nav-section";
      details.open = isCurrent;

      var summary = document.createElement("summary");
      if (isCurrent) {
        summary.setAttribute("aria-current", "page");
      }

      var titleLink = pageLink.cloneNode(true);
      titleLink.removeAttribute("aria-current");
      titleLink.addEventListener("click", function (event) {
        event.stopPropagation();
      });
      summary.appendChild(titleLink);
      details.appendChild(summary);

      var links = document.createElement("div");
      links.className = "subnav-links";
      sections.forEach(function (entry) {
        var link = document.createElement("a");
        link.href = (isCurrent ? "" : page) + "#" + entry.sectionId;
        link.textContent = entry.sectionTitle;
        links.appendChild(link);
      });

      details.appendChild(links);
      pageLink.replaceWith(details);
    });
  }

  function getSearchTerms(query) {
    return query
      .trim()
      .toLocaleLowerCase()
      .split(/\s+/)
      .filter(Boolean);
  }

  function getSnippet(text, terms) {
    var normalized = text.replace(/\s+/g, " ").trim();
    var lowerText = normalized.toLocaleLowerCase();
    var position = terms.reduce(function (best, term) {
      var found = lowerText.indexOf(term);
      return found >= 0 && (best < 0 || found < best) ? found : best;
    }, -1);

    if (position < 0) {
      position = 0;
    }

    var start = Math.max(0, position - 28);
    var end = Math.min(normalized.length, position + 72);
    return (start ? "…" : "") + normalized.slice(start, end) + (end < normalized.length ? "…" : "");
  }

  function searchEntries(query) {
    var terms = getSearchTerms(query);
    var entries = window.HELP_SEARCH_INDEX || [];

    if (!terms.length) {
      return [];
    }

    return entries
      .map(function (entry) {
        var pageTitle = entry.pageTitle.toLocaleLowerCase();
        var sectionTitle = entry.sectionTitle.toLocaleLowerCase();
        var text = entry.text.toLocaleLowerCase();
        var haystack = pageTitle + " " + sectionTitle + " " + text;

        if (!terms.every(function (term) { return haystack.indexOf(term) >= 0; })) {
          return null;
        }

        var score = terms.reduce(function (total, term) {
          if (sectionTitle.indexOf(term) >= 0) {
            total += 4;
          }
          if (pageTitle.indexOf(term) >= 0) {
            total += 3;
          }
          if (text.indexOf(term) >= 0) {
            total += 1;
          }
          return total;
        }, 0);

        return { entry: entry, score: score };
      })
      .filter(Boolean)
      .sort(function (left, right) { return right.score - left.score; })
      .slice(0, 12);
  }

  function buildSearch() {
    var subtitle = document.querySelector(".brand-subtitle");
    if (!subtitle) {
      return;
    }

    var wrapper = document.createElement("div");
    wrapper.className = "help-search";

    var label = document.createElement("label");
    label.htmlFor = "help-search-input";
    label.textContent = "Keyword Search";

    var input = document.createElement("input");
    input.id = "help-search-input";
    input.type = "search";
    input.placeholder = "Search all help content";
    input.autocomplete = "off";
    input.maxLength = 50;

    var results = document.createElement("div");
    results.className = "search-results";
    results.setAttribute("aria-live", "polite");
    results.hidden = true;

    wrapper.appendChild(label);
    wrapper.appendChild(input);
    wrapper.appendChild(results);
    subtitle.insertAdjacentElement("afterend", wrapper);

    function renderResults() {
      var query = input.value.trim();
      results.textContent = "";

      if (!query) {
        results.hidden = true;
        return;
      }

      var matches = searchEntries(query);
      if (!matches.length) {
        var empty = document.createElement("span");
        empty.className = "search-empty";
        empty.textContent = "No matching content found";
        results.appendChild(empty);
      } else {
        var terms = getSearchTerms(query);
        matches.forEach(function (match) {
          var entry = match.entry;
          var link = document.createElement("a");
          var hash = entry.sectionId ? "#" + entry.sectionId : "";
          link.className = "search-result";
          link.href = entry.page + "?q=" + encodeURIComponent(query) + hash;

          var title = document.createElement("span");
          title.className = "search-result-title";
          title.textContent = entry.pageTitle + " · " + entry.sectionTitle;

          var snippet = document.createElement("span");
          snippet.className = "search-result-snippet";
          snippet.textContent = getSnippet(entry.text, terms);

          link.appendChild(title);
          link.appendChild(snippet);
          results.appendChild(link);
        });
      }

      results.hidden = false;
    }

    input.addEventListener("input", renderResults);
    input.addEventListener("focus", renderResults);
    input.addEventListener("keydown", function (event) {
      if (event.key === "Escape") {
        results.hidden = true;
      }
    });
    document.addEventListener("click", function (event) {
      if (!wrapper.contains(event.target)) {
        results.hidden = true;
      }
    });
  }

  function highlightQuery() {
    if (!content) {
      return;
    }

    var query = new URLSearchParams(window.location.search).get("q") || "";
    var terms = getSearchTerms(query);
    if (!terms.length) {
      return;
    }

    var escapedTerms = terms.map(function (term) {
      return term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    });
    var pattern = new RegExp("(" + escapedTerms.join("|") + ")", "gi");
    var walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
    var nodes = [];
    var node;

    while ((node = walker.nextNode())) {
      if (node.nodeValue.trim() && !node.parentElement.closest("script, style, mark")) {
        nodes.push(node);
      }
    }

    nodes.forEach(function (textNode) {
      var parts = textNode.nodeValue.split(pattern);
      if (parts.length === 1) {
        return;
      }

      var fragment = document.createDocumentFragment();
      parts.forEach(function (part, index) {
        if (index % 2) {
          var mark = document.createElement("mark");
          mark.textContent = part;
          fragment.appendChild(mark);
        } else {
          fragment.appendChild(document.createTextNode(part));
        }
      });
      textNode.parentNode.replaceChild(fragment, textNode);
    });
  }

  buildPageNavigation();
  buildSearch();
  highlightQuery();

  if (window.location.hash) {
    window.requestAnimationFrame(function () {
      var target = document.getElementById(window.location.hash.slice(1));
      if (target) {
        target.scrollIntoView();
      }
    });
  }
}());
