import os
import re
import glob
import html
import logging
import datetime
import email.utils
from multiprocessing import Pool
from string import Template

import markdown
from markdown.extensions.toc import TocExtension

destpath_re = re.compile(r"\.md$")
logging.basicConfig(encoding="utf-8", level=logging.INFO)

cpu_count = os.cpu_count()


def convert(text):
	md = markdown.Markdown(extensions=["extra", "meta", TocExtension(anchorlink=True)])
	res = md.convert(text)
	return res, md.Meta


def render_post(fpath):
	destpath = destpath_re.sub(".html", fpath)
	logging.info("opening %s for parsing, dest %s", fpath, destpath)
	# from: https://python-markdown.github.io/reference/
	with open(fpath, "r", encoding="utf-8") as input_file:
		logging.info("reading %s", fpath)
		text = input_file.read()

	logging.info("parsing %s", fpath)
	out, meta = convert(text)

	title = meta.get("title")[0]
	date = meta.get("date")[0]
	draft = False
	if meta.get("draft"):
		draft = True

	title_out, _ = convert("# " + title)
	out = title_out + out

	logging.info("writing to %s", destpath)
	render_template(
		"index.html.tmpl", destpath, {"content": out, "more_title": " - " + title}
	)

	return {
		"title": title,
		"date": date,
		"fpath": fpath,
		"destpath": destpath,
		"draft": draft,
	}


def render_posts():
	files = glob.glob("posts/*.md")
	logging.info("found post files %s", files)
	posts = []
	logging.info("starting render posts with cpu_count: %d", cpu_count)
	with Pool(processes=cpu_count) as pool:
		posts = pool.map(render_post, files)

	logging.info("render_posts result: %s", posts)
	return posts


def posts_list_html(posts):
	post_tpl = """<li>
		<a href="{href}">{title}</a>
		<time datetime="{date}">{disp_date}</time>
	</li>"""
	out = '<ul class="blog-posts-list">'
	for post in posts:
		disp_date = datetime.datetime.fromisoformat(post.get("date")).strftime(
			"%Y-%m-%d"
		)
		out += post_tpl.format(
			href=post.get("destpath"),
			title=post.get("title"),
			date=post.get("date"),
			disp_date=disp_date,
		)
	return out + "</ul>"


def render_template(tpl_fname, out_fname, subs):
	with open(tpl_fname, "r", encoding="utf-8") as inf:
		tmpl = Template(inf.read())

	out = tmpl.substitute(subs)

	out_fname = os.path.join("public/", out_fname)

	with open(out_fname, "w", encoding="utf-8") as outf:
		outf.write(out)


def render_index(posts):
	content_html = posts_list_html(posts)
	render_template(
		"index.html.tmpl", "index.html", {"content": content_html, "more_title": ""}
	)


def rss_post_xml(post):
	tpl = """
	<item>
		<title>{title}</title>
		<link>{link}</link>
		<pubDate>{pubdate}</pubDate>
		<guid>{link}</guid>
		<description>{description}</description>
	</item>
	"""
	link = "https://cfebs.com/" + post["destpath"]

	with open(post["fpath"], "r", encoding="utf-8") as inf:
		text = inf.read()

	converted, _ = convert(text)

	pubdate = email.utils.format_datetime(datetime.datetime.fromisoformat(post["date"]))
	subs = {
		"title": post["title"],
		"link": link,
		"pubdate": pubdate,
		"description": converted,
	}

	for k, v in subs.items():
		subs[k] = html.escape(v)

	return tpl.format(**subs)


def render_rss_index(posts):
	items = ""
	for post in posts[:5]:
		items += rss_post_xml(post)

	subs = {
		"site_title": "cfebs.com",
		"site_link": "https://cfebs.com",
		"self_full_link": "https://cfebs.com/index.xml",
		"description": "Recent content from cfebs.com",
		"last_build_date": email.utils.format_datetime(datetime.datetime.now()),
	}
	for k, v in subs.items():
		subs[k] = html.escape(v)

	subs["items"] = items
	render_template("index.xml.tmpl", "index.xml", subs)


def main():
	os.makedirs("public/posts/", exist_ok=True)
	posts = render_posts()
	logging.info("rendered posts: %s", posts)
	posts = filter(lambda p: not p["draft"], posts)
	sorted_posts = sorted(
		posts, key=lambda p: datetime.datetime.fromisoformat(p["date"]), reverse=True
	)
	render_index(sorted_posts)
	render_rss_index(sorted_posts)


if __name__ == "__main__":
	main()
