const fs = require('fs-extra');
const dirname = require('path').dirname;
const Mustache = require('mustache');
const glob = require('glob');

const headerHtml = `<!doctype html>
<html>

<!--

!!! WARNING !!!

This file was auto-generated from {{{sourceMarkdownFile}}} and any manual change
made to it will be overwritten. To make a change to this file please modify
the source Markdown file:

https://github.com/laurent22/joplin/blob/dev/{{{sourceMarkdownFile}}}

-->

<head>
	<title>{{pageTitle}}</title>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="https://joplinapp.org/css/bootstrap.min.css">
	<link rel="shortcut icon" type="image/x-icon" href="https://joplinapp.org/favicon.ico">
	<!-- <link rel="stylesheet" href="https://joplinapp.org/css/fontawesome-all.min.css">  -->
	<link rel="stylesheet" href="https://joplinapp.org/css/fork-awesome.min.css"> 
	<script src="https://joplinapp.org/js/jquery-3.2.1.slim.min.js"></script>
	<style>
	body {
		background-color: #F1F1F1;
		color: #333333;
	}

	.root {
		overflow: hidden;
	}

	a[href^="mailto:"] {
		word-break: break-all;
	}

	table {
		margin-bottom: 1em;
	}
	td, th {
		padding: .8em;
		border: 1px solid #ccc;
	}

	.page-markdown table pre,
	.page-markdown table blockquote {
		margin-bottom: 0;
	}

	.page-markdown table pre,
	.page-markdown table blockquote {
		margin-bottom: 0;
	}

	.page-markdown table pre {
		background-color: rgba(0,0,0,0);
		border: none;
		margin: 0;
		padding: 0;
	}

	h1, h2 {
		border-bottom: 1px solid #eaecef;
		padding-bottom: 0.3em;
		font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
		font-weight: 600;
		font-size: 2em;
		margin-bottom: 16px;
	}
	h2 {
		font-size: 1.6em;
	}
	h3 {
		font-size: 1.3em;
	}
	code {
		color: black;
		background-color: #eee;
		border: 1px solid #ccc;
		font-size: .85em;
		word-break: break-all;
	}
	pre code {
		border: none;
	}
	pre {
		font-size: .85em;
	}
	blockquote {
		font-size: 1em;
		color: #555;
	};
	#toc ul {
		margin-bottom: 10px;
	}
	#toc > ul > li {
		margin-bottom: 10px;
	}
	#toc {
		padding-bottom: 1em;
	}
	.title {
		display: flex;
		align-items: center;
	}
	.title-icon {
		display: flex;
		height: 1em;
	}
	.title-text {
		display: flex;
		font-weight: normal;
		margin-bottom: .2em;
		margin-left: .5em;
	}
	.sub-title {
		font-weight: normal;
	}
	.container {
		background-color: white;
		padding: 0;
		box-shadow: 0 10px 20px #888888;
	}
	table.screenshots {
		margin-top: 2em;
		margin-bottom: 2em;
	}
	table.screenshots th {
		height: 3em;
		text-align: center;
	}
	table.screenshots th, 
	table.screenshots td {
		border: 1px solid #C2C2C2;
	}
	img[align="left"] {
		margin-right: 10px;
		margin-bottom: 10px;
	}
	.mobile-screenshot {
		height: 40em;
		padding: 1em;
	}
	.cli-screenshot-wrapper {
		background-color: black;
		vertical-align: top;
		padding: 1em 2em 1em 1em;
	}
	.cli-screenshot {
		font-family: "Monaco", "Inconsolata", "CONSOLAS", "Deja Vu Sans Mono", "Droid Sans Mono", "Andale Mono", monospace;
		background-color: black;
		color: white;
		border: none;
	}
	.cli-screenshot .prompt {
		color: #48C2F0;
	}
	.top-screenshot {
		margin-top: 2em;
		text-align: center;
	}
	.header {
		position: relative;
		padding-left: 2em;
		padding-right: 2em;
		padding-top: 1em;
		padding-bottom: 1em;
		color: white;
		background-color: #2B2B3D;
	}
	.header a h1 {
		color: white;
	}
	.header a:hover {
		text-decoration: none;
	}
	.content {
		padding-left: 2em;
		padding-right: 2em;
		padding-bottom: 2em;
		padding-top: 2em;
	}
	.forkme {
		position: absolute;
		right: 0;
		top:0;
	}
	.nav-wrapper {
		position: relative;
		width: inherit;
	}
	.nav {
		background-color: black;
		display: flex;
		flex-direction: row;
		align-items: center;
	}
	.nav.sticky {
		position:fixed;
		top: 0;
		width: inherit;
		box-shadow: 0 0 10px #000000;
	}
	.nav a {
		color: white;
		display: inline-block;
		padding: .6em .9em .6em .9em;
	}
	.nav ul {
		padding-left: 2em;
		margin-bottom: 0;
		display: table-cell;
		display: flex;
		width: 100%;
	}
	.nav ul li {
		display: inline-block;
		padding: 0;
	}
	.nav li.selected {
		background-color: #222;
		font-weight: bold;
	}
	.nav-right {
		display: flex;
		text-align: right;
		vertical-align: middle;
		line-height: 0;
		margin-right: 10px;
	}
	.nav-right .share-btn {
		display: none;
	}
	.nav-right .small-share-btn {
		display: none;
	}
	.footer {
		padding: 2em;
		border-top: 1px solid #d4d4d4;
		margin-top: 2em;
		color: gray;
		font-size: .9em;
	}
	a.heading-anchor {
		display: inline-block;
		opacity: 0;
		width: 1.3em;
		font-size: 0.7em;
		margin-left: 0.4em;
		line-height: 1em;
		text-decoration: none;
		transition: opacity 0.3s;
	}
	a.heading-anchor:hover,
	h1:hover a.heading-anchor,
	h2:hover a.heading-anchor,
	h3:hover a.heading-anchor,
	h4:hover a.heading-anchor,
	h5:hover a.heading-anchor,
	h6:hover a.heading-anchor {
		opacity: 1;
	}

	@media (min-width: 992px) {
		.content{
			display: flex;
		}

		#toc{
			display: block!important;
			align-self: flex-start;
			width: 300px;
			position: sticky; top: 20px; left: 0;            
		}

		.main{
			width: calc(100% - 300px);
		}
	}

	.bottom-links {
		display: flex;
		justify-content: center;
		border-top: 1px solid #d4d4d4;
		margin-top: 30px;
		padding-top: 25px;
	}

	@media all and (min-width: 400px) {
		.nav-right .share-btn {
			display: inline-block;
		}
		.nav-right .small-share-btn {
			display: none;
		}
	}
</style>
</head>

<body>

<div class="container root page-{{sourceMarkdownName}}">

<div class="header">
	<a class="forkme" href="https://github.com/laurent22/joplin"><img src="{{{imageBaseUrl}}}/ForkMe.png"/></a>
	<a href="https://joplinapp.org"><h1 class="title"><img class="title-icon" src="{{{imageBaseUrl}}}/Icon512.png"><span class="title-text">Joplin</span></h1></a>
	<p class="sub-title">An open source note taking and to-do application with synchronisation capabilities</p>
</div>

<div class="nav-wrapper">
	<div class="nav">
		<ul>
			<li class="{{selectedHome}}"><a href="{{baseUrl}}/" title="Home"><i class="fa fa-home"></i></a></li>
			<li><a href="https://discourse.joplinapp.org" title="Forum">Forum</a></li>
			<li><a class="help" href="#" title="Menu">Menu</a></li>
			<!-- <li><a class="gsod" href="https://joplinapp.org/gsod2020/" title="Google Season of Docs 2020">GSoD 2020</a></li> -->
		</ul>
		<div class="nav-right">
			<!--
				<iframe class="share-btn" src="https://www.facebook.com/plugins/share_button.php?href=http%3A%2F%2Fjoplinapp.org&layout=button&size=small&mobile_iframe=true&width=60&height=20&appId" width="60" height="20" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"></iframe>
				<iframe class="share-btn" src="https://platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fjoplinapp.org" width="62" height="20" title="Tweet" style="border: 0; overflow: hidden;"></iframe>
			-->
			<iframe class="share-btn share-btn-github" src="https://ghbtns.com/github-btn.html?user=laurent22&repo=joplin&type=star&count=true" frameborder="0" scrolling="0" width="100px" height="20px"></iframe>
		</div>
	</div>
</div>

<div class="content">
	{{{tocHtml}}}

	<div class="main">
`;

const footerHtmlTemplate = `
</div></div>

<div class="footer">
Copyright (C) 2016-YYYY Laurent Cozic
</div>
</body>
</html>
`;

const footerHtml = footerHtmlTemplate.replace('YYYY', new Date().getFullYear());

// const screenshotHtml = `
// <table class="screenshots">
// 	<tr>
// 		<th>
// 			Mobile
// 		</th>
// 		<th>
// 			Command line
// 		</th>
// 	</tr>
// 	<tr>
// 		<td>
// 			<img class="mobile-screenshot" src="docs/images/Mobile.png"/>
// 		</td>
// 		<td class="cli-screenshot-wrapper">
// 			<pre class="cli-screenshot">
// <span class="prompt">joplin:/My notebook$</span> ls -n 12
// [ ] 8am conference call ☎
// [ ] Make vet appointment
// [ ] Go pick up parcel
// [ ] Pay flat rent 💸
// [X] Book ferry 🚢
// [X] Deploy Joplin app
//     Open source stuff
//     Swimming pool time table 🏊
//     Grocery shopping list 📝
//     Work itinerary
//     Tuesday random note
//     Vacation plans ☀
// 			</pre>
// 		</td>
// 	</tr>
// </table>
// `;

const scriptHtml = `
<script>
	function stickyHeader() { 
		return; // Disabled

		if ($(window).scrollTop() > 179) {
			$('.nav').addClass('sticky'); 
		} else {
			$('.nav').removeClass('sticky');
		}
	}

	$('#toc').hide();

	$('.help').click(function(event) {
		event.preventDefault();
		$('#toc').show();
	});

	$(window).scroll(function() {
		stickyHeader();
	});

	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
	ga('create', 'UA-103586105-1', 'auto');
	ga('send', 'pageview');
</script>
`;

const rootDir = dirname(dirname(__dirname));

function markdownToHtml(md, templateParams) {
	const MarkdownIt = require('markdown-it');

	const markdownIt = new MarkdownIt({
		breaks: true,
		linkify: true,
		html: true,
	});

	markdownIt.core.ruler.push('checkbox', state => {
		const tokens = state.tokens;
		const Token = state.Token;
		const doneNames = [];

		const headingTextToAnchorName = (text, doneNames) => {
			const allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
			let lastWasDash = true;
			let output = '';
			for (let i = 0; i < text.length; i++) {
				const c = text[i];
				if (allowed.indexOf(c) < 0) {
					if (lastWasDash) continue;
					lastWasDash = true;
					output += '-';
				} else {
					lastWasDash = false;
					output += c;
				}
			}

			output = output.toLowerCase();

			while (output.length && output[output.length - 1] === '-') {
				output = output.substr(0, output.length - 1);
			}

			let temp = output;
			let index = 1;
			while (doneNames.indexOf(temp) >= 0) {
				temp = `${output}-${index}`;
				index++;
			}
			output = temp;

			return output;
		};

		const createAnchorTokens = anchorName => {
			const output = [];

			{
				const token = new Token('heading_anchor_open', 'a', 1);
				token.attrs = [
					['name', anchorName],
					['href', `#${anchorName}`],
					['class', 'heading-anchor'],
				];
				output.push(token);
			}

			{
				const token = new Token('text', '', 0);
				token.content = '🔗';
				output.push(token);
			}

			{
				const token = new Token('heading_anchor_close', 'a', -1);
				output.push(token);
			}

			return output;
		};

		let insideHeading = false;
		for (let i = 0; i < tokens.length; i++) {
			const token = tokens[i];

			if (token.type === 'heading_open') {
				insideHeading = true;
				continue;
			}

			if (token.type === 'heading_close') {
				insideHeading = false;
				continue;
			}

			if (insideHeading && token.type === 'inline') {
				const anchorName = headingTextToAnchorName(token.content, doneNames);
				doneNames.push(anchorName);
				const anchorTokens = createAnchorTokens(anchorName);
				// token.children = anchorTokens.concat(token.children);
				token.children = token.children.concat(anchorTokens);
			}
		}
	});

	const improveDocHtml = `
		<div class="bottom-links">
			<a href="https://github.com/laurent22/joplin/blob/dev/{{{sourceMarkdownFile}}}">
				<i class="fa fa-github"></i> Improve this doc
			</a>
		</div>`;

	return Mustache.render(headerHtml, templateParams) + markdownIt.render(md) + Mustache.render(improveDocHtml, templateParams) + scriptHtml + footerHtml;
}

let tocMd_ = null;
let tocHtml_ = null;
const tocRegex_ = /<!-- TOC -->([^]*)<!-- TOC -->/;
function tocMd() {
	if (tocMd_) return tocMd_;
	const md = fs.readFileSync(`${rootDir}/README.md`, 'utf8');
	const toc = md.match(tocRegex_);
	tocMd_ = toc[1];
	return tocMd_;
}

function replaceGitHubByJoplinAppLinks(md) {
	// let output = md.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/master\/readme\/(.*?)\/index\.md(#[^\s)]+|)/g, 'https://joplinapp.org/$1');
	return md.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\.md(#[^\s)]+|)/g, 'https://joplinapp.org/$1/$2');
}

function tocHtml() {
	if (tocHtml_) return tocHtml_;
	const MarkdownIt = require('markdown-it');
	const markdownIt = new MarkdownIt();
	let md = tocMd();
	md = md.replace(/# Table of contents/, '');
	md = replaceGitHubByJoplinAppLinks(md);
	tocHtml_ = markdownIt.render(md);
	tocHtml_ = `<div id="toc">${tocHtml_}</div>`;
	return tocHtml_;
}

function renderMdToHtml(md, targetPath, templateParams) {
	// Remove the header because it's going to be added back as HTML
	md = md.replace(/# Joplin\n/, '');

	templateParams.baseUrl = 'https://joplinapp.org';
	templateParams.imageBaseUrl = `${templateParams.baseUrl}/images`;
	templateParams.tocHtml = tocHtml();

	const title = [];

	if (!templateParams.title) {
		title.push('Joplin - an open source note taking and to-do application with synchronisation capabilities');
	} else {
		title.push(templateParams.title);
		title.push('Joplin');
	}

	md = replaceGitHubByJoplinAppLinks(md);

	templateParams.pageTitle = title.join(' | ');
	const html = markdownToHtml(md, templateParams);

	const folderPath = dirname(targetPath);
	fs.mkdirpSync(folderPath);

	fs.writeFileSync(targetPath, html);
}

async function readmeFileTitle(sourcePath) {
	const md = await fs.readFile(sourcePath, 'utf8');
	const r = md.match(/(^|\n)# (.*)/);

	if (!r) {
		throw new Error(`Could not determine title for Markdown file: ${sourcePath}`);
	} else {
		return r[2];
	}
}

function renderFileToHtml(sourcePath, targetPath, templateParams) {
	const md = fs.readFileSync(sourcePath, 'utf8');
	return renderMdToHtml(md, targetPath, templateParams);
}

function makeHomePageMd() {
	let md = fs.readFileSync(`${rootDir}/README.md`, 'utf8');
	md = md.replace(tocRegex_, '');

	// HACK: GitHub needs the \| or the inline code won't be displayed correctly inside the table,
	// while MarkdownIt doesn't and will in fact display the \. So we remove it here.
	md = md.replace(/\\\| bash/g, '| bash');

	return md;
}

async function main() {
	await fs.remove(`${rootDir}/docs`);
	await fs.copy(`${rootDir}/Assets/WebsiteAssets`, `${rootDir}/docs`);

	renderMdToHtml(makeHomePageMd(), `${rootDir}/docs/index.html`, { sourceMarkdownFile: 'README.md' });

	const mdFiles = glob.sync(`${rootDir}/readme/**/*.md`, {
		ignore: [
			// '**/node_modules/**',
		],
	}).map(f => f.substr(rootDir.length + 1));

	const sources = [];

	for (const mdFile of mdFiles) {
		const title = await readmeFileTitle(`${rootDir}/${mdFile}`);
		const targetFilePath = `${mdFile.replace(/\.md/, '').replace(/readme\//, 'docs/')}/index.html`;
		sources.push([mdFile, targetFilePath, { title: title }]);
	}

	const path = require('path');

	for (const source of sources) {
		source[2].sourceMarkdownFile = source[0];
		source[2].sourceMarkdownName = path.basename(source[0], path.extname(source[0]));
		renderFileToHtml(`${rootDir}/${source[0]}`, `${rootDir}/${source[1]}`, source[2]);
	}
}

main().catch((error) => {
	console.error(error);
});