/*
 * Implements a simple markdown blog loader that's used primarily in the
 * `rendered/pages/blog` example.  It supports generating an RSS/Atom/JSON
 * feed of pages, loading an index of .md pages, and render markdown with
 * the headers.  It uses the `lib/docgen.js:render_with_code` to do the
 * main markdown processing.
 */
import path from "path";
import glob from "fast-glob";
import assert from "assert";
import { render_with_code } from "./docgen.js";
import fs from "fs";
import { Feed } from "feed";
// have to use the client config to avoid pino crashing rollup with json errors
import { base_host } from "../client/config.js";

// caches the posts so we don't load them repeatedly during runs
const POSTS = {};

// this keeps POSTS alive, for some reason it disappears during processing
process.POSTS = POSTS;

/*
  Takes a directory of `.md` files and returns all of them rendered
  to HTML+Metadata using `lib/docgen.js:render_with_code`.

  + `source string` -- Source directory to read.
 */
export const load = (source) => {
  assert(source !== undefined, "source for markdown processing can't be undefined");
  // just a dumb cache to avoid reading the files over and over
  // cache only works if load isn't async!
  let cache = POSTS[source];

  if(cache === undefined) {
    cache = []; // this is fresh so make a new one

    let source_path = path.join(process.cwd(), "..", source);
    let posts_regex = path.join(source_path, "*.md");
    assert(!posts_regex.includes("//"), `You have a // in your path which fast-glob hates: ${posts_regex}`);

    const files = glob.sync(posts_regex.replace(/\\/g, "/"));

    for(let post of files.reverse()) {
      try {
        const {content, toc, metadata} = render_with_code(source_path, post);
        assert(content && toc && metadata, `Rendering ${source} failed.`);

        // so many Svelte builders (like 7ty) need slug that we should do it here
        cache.push({content, toc, metadata, slug: metadata.slug});
      } catch(error) {
        console.error(error, `Failure processing post: ${post}`);
      }
    }

    POSTS[source] = cache;
    return cache;
  } else {
    return cache;
  }
}

/*
  Renders the `/public/feed.rss`, `/public/feed.atom`, and `/public/feed.json` files
  based on the `index_config` and posts from `load`. The `index_config` is a `.json`
  file that describes the blog. The current configuration can be
  found in `renderd/feed_config.json`.


  + `index_config string` -- The path to the `feed_config.json` file.
  + `posts Array` -- List of posts.
 */
export const render_feed = (index_config, posts) => {
  const index = JSON.parse(fs.readFileSync(index_config));
  const feed = new Feed(index);
  index.updated = new Date();

  for(let post of posts) {
    post.url = `${base_host}/blog/${post.slug}/`;

    feed.addItem({
      title: post.metadata.title,
      id: post.metadata.url,
      link: post.metadata.url,
      date: new Date(post.metadata.date),
      description: post.metadata.summary,
      content: post.content,
      author: index.author
    });
  }

  fs.writeFileSync('../public/feed.rss', feed.rss2());
  fs.writeFileSync('../public/feed.json', feed.json1());
  fs.writeFileSync('../public/feed.atom', feed.atom1());
}

export default { load, render_feed };
