// const cheerio = require("cheerio");
const slugify = require("@sindresorhus/slugify"); // import slugify from '@sindresorhus/slugify';
const Cache = require("@11ty/eleventy-cache-assets");
const pluginTOC = require("eleventy-plugin-nesting-toc");
const markdownIt = require("markdown-it");
const markdownItAnchor = require("markdown-it-anchor");
const { DateTime } = require("luxon");
const jsdom = require("jsdom");
const { JSDOM } = jsdom;

module.exports = function(eleventyConfig) {
  const markdown = require("markdown-it")({
    html: true,
    breaks: true,
    linkify: true,
  });

  eleventyConfig.addFilter("markdownify", function(rawString) {
    return markdown.render(rawString);
  });
  eleventyConfig.addFilter("markdowninline", function(rawString) {
    return markdown.renderInline(rawString);
  });

  eleventyConfig.addFilter("wbrToUrl", function(value) {
    const dom = new JSDOM(value);
    let links = dom.window.document.body.querySelectorAll('a[href^="http"], a[href^="www"]');
    links.forEach((link) => {
      link.innerHTML = link.innerHTML
        .replace(/\/\//g, "//\u003Cwbr\u003E")
        .replace(/\,/g, ",\u003Cwbr\u003E")
        .replace(/(\/|\~|\-|\.|\,|\_|\?|\#|\%)/g, "\u003Cwbr\u003E$1")
        .replace(/\-/g, "\u003Cwbr\u003E‑");
    });
    return dom.serialize();
  });

  eleventyConfig.addFilter("markdowninline", function(rawString) {
    return markdown.renderInline(rawString);
  });

  eleventyConfig.addCollection("menuByOrder", function(collectionApi) {

    return collectionApi
      .getAll()
      .filter((item) => {
        return item.data.menu;
      })

      .sort((a, b) => {
        if (a.data.menu) {
          if (a.data.order > b.data.order) return 1;
          else if (a.data.order < b.data.order) return -1;
          else return 0;
        }
      });
  })
  eleventyConfig.addCollection("sortedByOrder", function(collectionApi) {
    return collectionApi
      .getAll()
      .filter((item) => {
        return item.data.menu;
      })

      .sort((a, b) => {
        if (a.data.menu) {
          if (a.data.order > b.data.order) return 1;
          else if (a.data.order < b.data.order) return -1;
          else return 0;
        }
      });
  });

  eleventyConfig.addCollection("blog", (collectionApi) => {
    return collectionApi
      .getFilteredByGlob("src/blog/posts/*.md")
      .filter(a => { return a.data.published == true })
      .sort((a, b) => a.data.date - b.data.date);
  });

  eleventyConfig.addCollection("articles", (collectionApi) => {
    return collectionApi
      .getFilteredByGlob("src/articles/*.md")
      .sort((a, b) => a.data.date - b.data.date);
  });

  // eleventyConfig.addFilter("search", searchFilter);

  // eleventyConfig.addFilter("searchSingle", searchFilterSingle);
  eleventyConfig.addCollection("allSearch", (collection) => {
    return [...collection.getFilteredByTag("chapter")];
  });

  eleventyConfig.addPassthroughCopy({ "static/css": "/css" });
  eleventyConfig.addPassthroughCopy({ "static/fonts": "/fonts" });
  eleventyConfig.addPassthroughCopy({ "static/js": "/js" });
  eleventyConfig.addPassthroughCopy({ "static/images": "/images" });
  eleventyConfig.addPassthroughCopy({ "static/outputs": "/outputs" });
  eleventyConfig.addPassthroughCopy({ "static/admin": "/admin" });

  // plugin TOC
  eleventyConfig.addPlugin(pluginTOC);
  eleventyConfig.setLibrary(
    "md",
    markdownIt({
      html: true,
      linkify: true,
      typographer: true,
    }).use(markdownItAnchor, {})
  );

  // useful to use the toc somewhere else
  eleventyConfig.addFilter("prependLinks", function(value, prepend) {
    return value.replace(/<a href="/g, `<a href="${prepend}`);
  });
  eleventyConfig.addFilter(
    "replaceWithRegex",
    function(replaceThat, replaceWith) {
      let regex = new RegExp(replaceThat);
      return value.replace(regex, replaceWith);
    }
  );

  // add latin number plugin
  eleventyConfig.addFilter("romanize", function(value) {
    return romanize(value);
  });

  // \get the date with luxon (for all date)
  eleventyConfig.addFilter("postDate", (dateObj) => {
    let date = new Date(dateObj);
    return DateTime.fromJSDate(date).toLocaleString(DateTime.DATE_MED);
  });

  // limit the amount of items
  eleventyConfig.addFilter("limit", function(arr, limit) {
    return arr.slice(0, limit);
  });

  eleventyConfig.addFilter("filterContent", function(value, el) {
    // console.log(value);
    const $ = cheerio.load(value);
    if ($.html(el)) {
      return (value = $.html(el));
    } else {
      return value;
    }
  });

  eleventyConfig.addPlugin(pluginTOC, {
    tags: ["h2", "h3", "h4"], // which heading tags are selected headings must each have an ID attribute
    wrapper: "nav", // element to put around the root `ol`/`ul`
    wrapperClass: "toc", // class for the element around the root `ol`/`ul`
    ul: false, // if to use `ul` instead of `ol`
    flat: false,
  });

  eleventyConfig.addFilter("slugify", function(str) {
    return slugify(str, {
      lower: true,
      replacement: "-",
      remove: /[*+~.·,()'"`´%!?¿:@]/g,
    });
  });

  // folder structures
  // -----------------------------------------------------------------------------
  // content, data and layouts comes from the src folders
  // output goes to public (for gitlab ci/cd)
  // -----------------------------------------------------------------------------
  return {
    dir: {
      input: "src",
      output: "public",
      includes: "layouts",
      data: "data",
    },
  };
};

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

function romanize(num) {
  // taken from Steven Levithan
  // https://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

  if (isNaN(num)) return NaN;
  var digits = String(+num).split(""),
    key = [
      "",
      "C",
      "CC",
      "CCC",
      "CD",
      "D",
      "DC",
      "DCC",
      "DCCC",
      "CM",
      "",
      "X",
      "XX",
      "XXX",
      "XL",
      "L",
      "LX",
      "LXX",
      "LXXX",
      "XC",
      "",
      "I",
      "II",
      "III",
      "IV",
      "V",
      "VI",
      "VII",
      "VIII",
      "IX",
    ],
    roman = "",
    i = 3;
  while (i--) roman = (key[+digits.pop() + i * 10] || "") + roman;
  return Array(+digits.join("") + 1).join("M") + roman;
}

function cleanLink(content) {
  //add wbr to / in links
  const links = content.querySelectorAll('a[href^="http"], a[href^="www"]');
  links.forEach((link) => {
    // Rerun to avoid large spaces. Break after a colon or a double slash (//) or before a single slash (/), a tilde (~), a period, a comma, a hyphen, an underline (_), a question mark, a number sign, or a percent symbol.
    const content = link.textContent;
    let printableUrl = content.replace(/\/\//g, "//\u003Cwbr\u003E");
    printableUrl = printableUrl.replace(/\,/g, ",\u003Cwbr\u003E");
    // put wbr around everything.
    printableUrl = printableUrl.replace(
      /(\/|\~|\-|\.|\,|\_|\?|\#|\%)/g,
      "\u003Cwbr\u003E$1"
    );
    // turn hyphen in non breaking hyphen
    printableUrl = printableUrl.replace(/\-/g, "\u003Cwbr\u003E&#x2011;");
    link.setAttribute("data-print-url", printableUrl);
    link.innerHTML = printableUrl;
  });
}