<script lang="ts">
import { onMount, tick } from "svelte";
import HomePage from "home_page/HomePage.svelte";
import LoginRouter from "login/Router.svelte";
import HomeRouter from "user_home/Router.svelte";
import AdminRouter from "admin_panel/Router.svelte";
import Filesystem from "filesystem/Filesystem.svelte";
import NotFound from "./NotFound.svelte";
import SpeedtestPage from "speedtest/SpeedtestPage.svelte";
import Appearance from "pages/Appearance.svelte";
import Footer from "layout/Footer.svelte";
import { current_page_store, type Tab } from "./RouterStore";
import { get_user, type User } from "lib/NovaAPI";
import { breadcrumbs_store } from "./BreadcrumbStore";

let pages: Tab[] = [
	{
		path: "/",
		title: "Home",
		component: HomePage,
	}, {
		path: "/login",
		title: "Login",
		component: LoginRouter,
	}, {
		path: "/register",
		title: "Register",
		component: LoginRouter,
	}, {
		path: "/user",
		prefix: "/user/",
		title: "Dashboard",
		component: HomeRouter,
		login: true,
	}, {
		path: "/d/me",
		prefix: "/d/",
		title: "Filesystem",
		component: Filesystem,
		footer: false,
		custom_breadcrumbs: true,
	}, {
		path: "/admin",
		prefix: "/admin/",
		title: "Admin Panel",
		component: AdminRouter,
		login: true,
	}, {
		path: "/speedtest",
		title: "Speedtest",
		component: SpeedtestPage,
	}, {
		path: "/appearance",
		title: "Appearance",
		component: Appearance,
	},
]

onMount(async () => {
	await load_page(window.location.pathname, false)
})

let current_page: Tab = $state(null)

const load_page = async (pathname: string, history: boolean): Promise<boolean> => {
	console.debug(
		"Page router: Navigating to page", pathname,
		"current path", window.location.pathname,
		"log history:", history,
	)

	let user: User
	try {
		user = await get_user()
	} catch (err) {
		alert("Failed to get user details: " + err)
	}

	const path_decoded = decodeURIComponent(pathname)
	let page_by_path: Tab = null
	let page_by_prefix: Tab = null
	for (const page of pages) {
		if (path_decoded === page.path) {
			page_by_path = page
		}
		if (page.prefix !== undefined && path_decoded.startsWith(page.prefix)) {
			page_by_prefix = page
		}
	}

	if (page_by_path !== null) {
		current_page = page_by_path
	} else if (page_by_prefix !== null) {
		current_page = page_by_prefix
	} else {
		current_page = {
			path: "",
			title: "Not Found",
			component: NotFound,
		}
		return false
	}

	// If this page requires login, and the user is not logged in, then we
	// redirect the user to the login page
	if (current_page.login === true && (user === null || user === undefined)) {
		console.debug("User is not logged in, redirecting to login page", user)
		return load_page("/login", true)
	}

	window.document.title = current_page.title+" / Nova"

	if (history) {
		window.history.pushState({}, window.document.title, pathname)
	}

	if (current_page.custom_breadcrumbs !== true) {
		breadcrumbs_store.set(breadcrumbs)
	}

	// The current_page_store updates all the listening pages for navigation
	// events. We first wait for a tick so that the current page gets unmounted
	// before sending the event. That way a stale page will not get events which
	// are not meant for them
	tick().then(() => {
		current_page_store.set(current_page)
	})

	return true
}

const click = async (e: MouseEvent) => {
	const origin = (e.target as Element).closest("a");

	if (origin === null) {
		return
	}

	const url = URL.parse(origin.href)
	if (window.location.host !== url.host) {
		return
	}

	console.log("Caught link click to", url.pathname);

	// Try to load the page, if the page was found we cancel the browser
	// navigation event so we can handle it ourselves
	if (await load_page(url.pathname, true) === true) {
		e.preventDefault()
	}
}

const popstate = (e: PopStateEvent) => {
	load_page(window.location.pathname, false)
}
</script>

{#snippet breadcrumbs()}
	{current_page.title}
{/snippet}

<svelte:document onclick={click}/>
<svelte:window onpopstate={popstate}/>

{#if current_page !== null}
	<current_page.component />

	{#if current_page.footer !== false}
		<Footer/>
	{/if}
{/if}
