import { promises as fs } from "fs";
import path from "path";
import dateFns from "date-fns";
import slugify from "@sindresorhus/slugify";
import * as util from "../util";
import * as metadata from "../metadata";
import { Page, PostMetadata } from "../metadata";
import * as markdown from "../markdown";
import layout from "../layout";

async function generatePostFromFile(postPath: string, additionalMetadata: object = {}): Promise<Page> {
	const page = await metadata.get(postPath);

	(<PostMetadata>page.metadata).tagSlugs = (<PostMetadata>page.metadata).tags.map((tag) => slugify(tag));

	for (const k in additionalMetadata) {
		if (additionalMetadata.hasOwnProperty(k)) page.metadata[k] = additionalMetadata[k];
	}
	
	if (!(<PostMetadata>page.metadata).permalink) {
		let postMeta = <PostMetadata>page.metadata;
		postMeta.date = dateFns.parse(postMeta.date);
		postMeta.slug = postMeta.slug || slugify(postMeta.title);
		postMeta.permalink = `/${postMeta.date.getFullYear()}/${postMeta.slug}/`;
	}

	if (page.metadata.source && page.metadata.source!.endsWith(".md")) {
		(<PostMetadata>page.metadata).wordCount = util.getWordCount(page.text);
		(<PostMetadata>page.metadata).readingTime = util.getReadingTime((<PostMetadata>page.metadata).wordCount);

		page.text = markdown.render(page.text);
	}

	page.text = util.render(page.text, { metadata: page.metadata }, postPath);

	// todo: handle word count if not .md

	if (!(<PostMetadata>page.metadata).excerpt) {
		const parts = page.text.split("<!-- excerpt-end -->");
		if (parts.length > 1) {
			(<PostMetadata>page.metadata).excerpt = parts[0];
		}
	}

	return page;
}

async function generatePostFromDirectory(dir: string): Promise<Page> {
	const files = await fs.readdir(dir);

	let indexPath: string;
	for (const f of files) {
		if (f.split(".")[0] === "index") {
			indexPath = path.join(dir, f);
			break;
		}
	}

	if (!indexPath) {
		throw new Error(`Unable to find index file for post: ${dir}`);
	}

	return await generatePostFromFile(indexPath, {
		sourceDir: dir
	});
}

export default async function posts(): Promise<Page[]> {
	const posts: Page[] = [];

	const files = await fs.readdir("site/posts");
	for (const f of files) {
		const postPath = path.join("site/posts", f);
		const stats = await fs.stat(postPath);
		
		let page: Page;

		if (stats.isDirectory()) {
			page = await generatePostFromDirectory(postPath);
		} else {
			page = await generatePostFromFile(postPath);
		}

		const renderedText = await layout(page.text, page.metadata, page.metadata.layout || "article.html.ejs");

		let dest = page.metadata.permalink;
		if (dest.endsWith("/")) {
			dest += "index.html";
		}

		util.write(dest, renderedText);

		posts.push(page);
	}

	return posts;
}
