// Format a date string into a time since
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), "minute");
	return _format(Math.floor(seconds), "second");
}

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

	root.querySelectorAll("a").forEach(e => {
		if (e.href == "") e.href = "https://" + e.innerText;
	});

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


	// Sort journal entries into nested structure of year>month>day
	const post_parent = document.getElementById("posts");
	post_parent.querySelectorAll("[data-server-date]") .forEach(e => {
		const monthtostr = (num) => new Intl.DateTimeFormat('en-US', { month: 'long' }).format(new Date(2000, num));
		const date = e.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;

		let ycat = document.getElementsByClassName(year)[0];


		// Create year catagory if it does not exist
		if (!ycat){
			ycat = document.createElement("li");
			ycat.innerHTML = `<b>${year}:</b>`

			const ycat_inner = document.createElement("ul");
			ycat.append(ycat_inner);
			ycat_inner.classList.add(year);
			post_parent.append(ycat);
			ycat = ycat_inner;
		}


		// Do the same for the month
		let  mcat = ycat.getElementsByClassName(month)[0];
		if (!mcat){
			mcat = document.createElement("li");
			mcat.innerHTML = `<b>${monthtostr(month)}:</b>`

			const mcat_inner = document.createElement("ul");
			mcat.append(mcat_inner);
			mcat_inner.classList.add(month);
			ycat.append(mcat);
			mcat = mcat_inner;
		}

		mcat.append(e);
	});


	// 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();
