import MarkdownIt from "markdown-it";
import MarkdownItFootnote from "markdown-it-footnote";
import slugify from "@sindresorhus/slugify";
import * as util from "./util";
import { URL } from "url";

const md = new MarkdownIt({
	highlight: util.highlight,
	html: true,
	typographer: true
});

md.use(MarkdownItFootnote);

// Inserts heading anchors
// Based on https://github.com/valeriangalliat/markdown-it-anchor
md.core.ruler.push("header anchor", (state) => {
	const tokens = state.tokens;

	tokens
		.filter((token) => token.type === "heading_open")
		.forEach((token) => {
			const index = tokens.indexOf(token);
			const title = tokens[index + 1]
				.children
				.filter((token) => token.type === "text" || token.type == "code_inline")
				.reduce((acc, t) => acc + t.content, "");
			
			let slug = token.attrGet("id") || slugify(title);
			if (token.attrGet("id") == null) {
				token.attrPush(["id", slug]);
			}
			
			const linkTokens = [
				Object.assign(new state.Token("link_open", "a", 1), {
					attrs: [
						["class", "header-anchor"],
						["href", "#" + slug],
						["aria-hidden", "true"],
						["role", "presentation"]
					]
				}),
				Object.assign(new state.Token("html_block", "", 0), { content: token.markup }),
				new state.Token("link_close", "a", -1),
				Object.assign(new state.Token("text", "", 0), { content: " " })
			];
		
			state.tokens[index + 1].children.unshift(...linkTokens);
		});
});

// Adds data-link attributes to anchor elements
const defaultRenderer = md.renderer.rules.link_open || function(tokens, index, options, env, self) {
	return self.renderToken(tokens, index, options);
};
md.renderer.rules.link_open = function(tokens, index, options, env, self) {
	const href = tokens[index].attrGet("href");
	if (href != null) {
		try {
			const parsed = new URL(href);
			let hostname = parsed.hostname;

			// hide wwww from beginning of domain
			if (hostname.startsWith("www.")) {
				hostname = hostname.substr(4);
			}

			// if the path is /, omit it
			const formattedPathname = parsed.pathname === "/" ? "" : parsed.pathname;

			let formatted = `${hostname}${formattedPathname}`;

			if (hostname.endsWith("youtube.com") && formattedPathname == "/watch") {
				// otherwise yt video links end up as `youtube.com/watch` which looks weird
				formatted += parsed.search;
			}

			if (formatted.length > 40) {
				formatted = formatted.substr(0, 40) + "...";
			}
			tokens[index].attrPush(["data-link", formatted]);
		} catch (e) {
			tokens[index].attrPush(["data-link", href]);
		}
	}

	return defaultRenderer(tokens, index, options, env, self);
};

export function render(text: string): string {
	return md.render(text);
}
