const Path = require('path');
const nunjucks = require('nunjucks');
const marked = require('marked');

function njkFind (ary, key, value) {
	if (!ary.find) {
		return ary[key];
	}
	if (typeof value == 'undefined') {
		return ary.find(i => i.hasOwnAttribute(key));
	} else {
		return ary.find(i => i[key] == value);
	}
}

function njkCollect (entries, key, collectables) {
	const out = [];
	for (const entry of entries) {
		if (out.find(i => i[key] == entry[key])) {
			continue;
		}
		const others = entries.filter(item => item[key] == entry[key]);
		const obj = Object.assign({}, entry);
		for (const collectable of collectables) {
			obj[collectable] = others.map(i => i[collectable]).filter(i => typeof i !== "undefined" && i !== "");
		}
		out.push(obj);
	}
	return out;
}

function njkGet (entries, key) {
	return entries.map(i => i[key]);
}

function njkUnique (entries) {
	return entries.filter((element, index, array) => array.indexOf(element) === index);
}

function njkPadStart (str, len, chr) {
	return String(str).padStart(len, chr);
}

function njkTimestamp (arg, precision = "seconds") {
	let str;
	if (arg) {
		if (typeof arg.toISOString === "function") {
			str = arg.toISOString();
		} else if (arg == "now") {
			str = (new Date()).toISOString();
		}
		const ts = new Date(arg);
		if (!isNaN(ts)) {
			str = ts.toISOString();
		}

		if (str) {
			str = str.replace("T", " ");
			if (precision.toLowerCase().startsWith("s")) {
				str = str.substr(0, 19)+"Z";
			} else if (precision.toLowerCase().startsWith("m")) {
				str = str.substr(0, 16)+"Z";
			} else if (precision.toLowerCase().startsWith("h")) {
				str = str.substr(0, 13)+"Z";
			} else if (precision.toLowerCase().startsWith("d")) {
				str = str.substr(0, 10)+"Z";
			}
			return str;
		}
	}
	return arg;
}

function njkMarkdown (str) {
	return marked.parse(String(str));
}

function njkMarkdownInline (str) {
	return marked.parseInline(String(str));
}

async function render (data, template) {

	const nenv = nunjucks.configure(Path.dirname(template), {autoescape: false, lstripBlocks: false, trimBlocks: false});
	nenv.addFilter('find', njkFind);
	nenv.addFilter('unique', njkUnique);
	nenv.addFilter('collect', njkCollect);
	nenv.addFilter('get', njkGet);
	nenv.addFilter('padStart', njkPadStart);
	nenv.addFilter('timestamp', njkTimestamp);
	nenv.addFilter('markdown', njkMarkdown);
	nenv.addFilter('markdownInline', njkMarkdownInline);

	const view = nenv.render(Path.basename(template), data);

	return view;
}

module.exports = render;
