
function time_since(date) {
	const _format = (time, ext) =>
		`${time} ${ext}${time > 1 ? "s" : ""} ago`;

	const old_date = new Date(date);
	let seconds = Math.floor((new Date() - old_date) / 1000);

	var interval = seconds / 31536000;
	if (interval > 1)
		return _format(Math.floor(interval), "year");

	interval = seconds / 2592000;
	if (interval > 1)
		return _format(Math.floor(interval), "month");

	interval = seconds / 86400;
	if (interval > 1)
		return _format(Math.floor(interval), "day");

	interval = seconds / 3600;
	if (interval > 1)
		return _format(Math.floor(interval), "hour");

	interval = seconds / 60;
	if (interval > 1)
		return _format(Math.floor(interval), " month");

	return _format(Math.floor(seconds), "second");
}

// initialise page
function init_page(root){
	if (root == undefined)
		root = document;

	
	// Generate timestamp on posts
	root.querySelectorAll(".date").forEach(element => {
		element.innerText = time_since(element.innerText);
	});


	// Moves an element into a parent container,
	// the container will be created if it does
	// not already exist.
	//
	function move_to(element, parent_id, label_callback = ()=>{return "Label"}){
		// Create the parent if it does not exist
		const parent_element = root.querySelector(`#${parent_id}`)
			|| root.body.appendChild(document.createElement("div"));
	
		// Add metadata
		if (parent_element.id == ""){
			parent_element.id = parent_id;
			const label = root.createElement("p");
			label.innerHTML = label_callback();
			parent_element.appendChild(label);
		}
	
		if (!parent_element.classList.contains("cat"))
			parent_element.classList.add("cat")
	
		// Move child to parent
		parent_element.appendChild(element);
		return parent_element;
	}
	

	// Sort journal entries into nested structure of year>month>day
	root.querySelectorAll("#posts [data-server-date]") .forEach(element => {
		const date = element.getAttribute("data-server-date");
		const split_date = date.split(/-| /);
	
		// Get the date values from element
		const year = Number(split_date[0]);
		const month = Number(split_date[1])-1;
	
		// Move element to year container
		const year_container =
			move_to(element, `cat-year-${year}`, () => {
				const current_year = new Date().getFullYear()
				if (year == current_year)
					return `<b title="${year}">This year:</b>`;
	
				else if (year == current_year-1) return `<span class="${year}">Last year:</span>`;
				else return String(year);
			});
	
		// Move element to month container
		const month_container =
			move_to(element, `cat-month-${month}`, () => {
				const current_month = new Date().getMonth();
				if (month == current_month) return `<span class="current" title="${month + 1}/${year}">This month:</span>`;
				if (month == current_month - 1) return `<span title="${month + 1}/${year}">Last month:</span>`;
	
				// Return the month as a string
				return  [
					"January", "February", "March", "April", "May", "June",
					"July", "August", "September", "October", "November", "December"
				][month];
			});
	
		element.firstChild.innerHTML += ` <i>(${time_since(date)})</i>`;
		element.title = date;
	
		// Move month into the year (nested)
		year_container.appendChild(month_container);
		element.removeAttribute("data-server-date");
	});


	// Preloader for static-origin pages
	root.querySelectorAll(".preload-a").forEach(e => {
		let doc, head, body;
	
		// Load the links page content in the background
		async function load_link_page(){
			try {
				
				// Fetch the page
				const resp = await fetch(e.href, { priority: "low" });
				if (!resp.ok){
					console.error("Failed to fetch website content");
					return;
				}

				// Load the html using a DOMParser
				doc = new DOMParser()
					.parseFromString(await resp.text(), "text/html");


				// Remove event listener
				e.removeEventListener("mouseover", load_link_page);
	
			// Error handling
			} catch (err){
				console.error(err);
			}
		}

		// Load the link on hover on link.
		// Usually a user takes about half a second to actually click the
		// button, this is plenty of time for the page to be loaded in the
		// background and prepared for replaceing the current dom.
		//if (window.width > window.height)
		//	e.addEventListener("mouseover", load_link_page);
		load_link_page()

		// If the user is in portrait mode then mouseenter is useless, we
		// can instead just run the preload function in the background.

		// Replace the roots pages content with the new one on click
		e.addEventListener("mousedown", async (ev)  => {
			const start = performance.now();
			init_page(doc);

			// Get just the body and head (not the html tag)
			head = doc.head;
			body = doc.body;

			body.style.opacity = 1;

			// Replace the head (without flickering is quite difficult)
			const old_head = [ ...document.head.children ];
			const new_head = [ ...head.children ];

			// Add new elements to the head
			for (const new_e of new_head){
				const exists = old_head.some(old_e => old_e.isEqualNode(new_e));
				if (!exists) document.head.appendChild(new_e.cloneNode(true));
			}

			// Then remove obselete styles
			for (const old_e of old_head){
				const exists = new_head.some(new_e => old_e.isEqualNode(new_e));
				if (!exists) old_e.remove();
			}

			// Replace the pages body
			document.body.replaceWith(body);

			// Set the pages url to the new loaded page
			window.history.pushState({ page: 1 }, e.href, e.href);

			const end = performance.now();
			console.log(`${end - start}ms to display page ${e.href}`);
			ev.preventDefault();
		});
	})
}


// Initialise page
document.body.style.opacity = 1;
init_page();

window.addEventListener("pageshow", ()=>{
	const entries = performance.getEntriesByType("navigation");
	if (entries.length > 0 && entries[0].type === "back_forward")
		location.href = "";
});
