<script lang="ts">
	import { page } from '$app/state';
	import { slide, fade } from 'svelte/transition';
	import { onMount } from 'svelte';
	import { browser } from '$app/environment';
	import { navigating } from '$app/state';
	import { LOCATIONS } from '$lib/locations-object.svelte';

	import Loading from '$lib/components/ui/Loading.svelte';
	import TimezoneWarning from '$lib/components/ui/TimezoneWarning.svelte';

	import '$lib/global.css';

	import logoText from '$lib/assets/round-logo-text.svg';
	import logoPlain from '$lib/assets/round-logo.svg';
	import favicon from '$lib/assets/round-logo.svg';

	import {
		IconHome,
		IconDialpad,
		IconSettings,
		IconHelp,
		IconDots,
		IconSpy
	} from '@tabler/icons-svelte-runes';

	onMount(async () => {
		LOCATIONS.init();
		if (browser && 'serviceWorker' in navigator) {
			try {
				const registration = await navigator.serviceWorker.register('/service-worker.js', {
					type: 'module'
				});
				console.info('OwlBoard Service Worker registered', registration.scope);
			} catch (error) {
				console.error('Service Worker installation failed: ', error);
			}
		}
	});

	let { children } = $props();

	// Navigation State

	const moreIcon = IconDots;

	const navItems = [
		{ label: 'Home', path: '/', icon: IconHome },
		{ label: 'PIS', path: '/pis/', icon: IconDialpad },
		{ label: 'Options', path: '/preferences/', icon: IconSettings },
		{ label: 'About', path: '/about/', icon: IconHelp },
		{ label: 'Privacy Policy', path: '/privacy/', icon: IconSpy }
	];

	let navWidth = $state(0);
	let menuOpen = $state(false);
	const ITEM_WIDTH = 110;
	const MORE_BUTTON_WIDTH = 110;

	const activePath = $derived(page.url?.pathname ?? '');

	const visibleCount = $derived.by(() => {
		if (navWidth === 0) return navItems.length;
		const available = navWidth;
		const totalItems = navItems.length;
		const countWithoutMore = Math.floor(available / ITEM_WIDTH);

		if (countWithoutMore >= totalItems) return totalItems;

		const availableWithMore = navWidth - MORE_BUTTON_WIDTH;
		const countWithMore = Math.floor(availableWithMore / ITEM_WIDTH);

		if (totalItems - countWithMore === 1) {
			if (available >= (countWithMore + 1) * ITEM_WIDTH) {
				return totalItems;
			}
		}

		return countWithMore;
	});

	const visibleItems = $derived(navItems.slice(0, visibleCount));
	const hiddenItems = $derived(navItems.slice(visibleCount));
</script>

<svelte:head>
	<link rel="icon" href={favicon} />
</svelte:head>

<header>
	<a href="/" aria-label="OwlBoard Home" class="logo-link">
		{#if page.data.title}
			<img src={logoPlain} alt="OwlBoard Icon" height="55" />
		{:else}
			<img src={logoText} alt="OwlBoard Logo" height="55" />
		{/if}
	</a>
	{#if page.data.title}
		<h1 class="page-title">{page.data.title}</h1>
	{/if}
</header>

<main>
	<TimezoneWarning />

	{#if navigating && navigating.to}
		<Loading />
	{:else}
		{@render children()}
	{/if}
</main>

<nav bind:clientWidth={navWidth}>
	<!-- Dynamic Nav Elements Here! -->
	{#each visibleItems as item}
		{@const isActive = activePath.replace(/\/$/, '') === item.path.replace(/\/$/, '')}
		{@const Icon = item.icon}
		<a
			href={item.path}
			class="nav-item"
			class:active={isActive}
			aria-current={isActive ? 'page' : undefined}
			onclick={() => (menuOpen = false)}
		>
			<Icon size={24} stroke={isActive ? 2 : 1.5} class="nav-icon" />

			<span class="label">{item.label}</span>
		</a>
	{/each}
	{#if hiddenItems.length > 0}
		<div class="more-menu-wrapper">
			<button
				class="nav-item more-btn"
				onclick={() => (menuOpen = !menuOpen)}
				aria-expanded={menuOpen}
			>
				<IconDots size={24} />
				<span class="label">More</span>
			</button>
		</div>
		{#if menuOpen}
			<div
				class="backdrop"
				onclick={() => (menuOpen = false)}
				transition:fade={{ duration: 150 }}
			></div>
			<div class="menu-popover" transition:slide={{ axis: 'y', duration: 250 }}>
				{#each hiddenItems as item}
					{@const isActive = activePath.replace(/\/$/, '') === item.path.replace(/\/$/, '')}
					{@const Icon = item.icon}
					<a
						href={item.path}
						class="menu-popover-item"
						onclick={() => (menuOpen = false)}
						class:active={isActive}
						aria-current={isActive ? 'page' : undefined}
					>
						<Icon size={20} />
						<span>{item.label}</span>
					</a>
				{/each}
			</div>
		{/if}
	{/if}
</nav>

<div class="viewport-guard">
	<img src={logoPlain} alt="OwlBoard Logo" width="100" height="100" />
	<h1 class="viewport-guard-title">Narrow Gauge Detected</h1>
	<p>
		Just as trains need the right track width, our data needs a bit more room to stay on the rails.
		Please expand your view to at least 320px to view the app.
	</p>
</div>

<style>
	header {
		top: 0;
		height: var(--header-height);
		box-shadow: var(--shadow-std);
	}
	.logo-link {
		width: auto;
		display: block;
		height: 55px;
	}

	.logo-link img {
		height: 55px;
		width: auto;
		display: block;
	}

	.page-title {
		font-family: 'URW Gothic', sans-serif;
		font-weight: 600;
		font-size: clamp(0.9rem, 2.5vw + 0.8rem, 2rem);
		font-style: normal;
		margin-left: 5px;
		padding-bottom: 2px;
		color: var(--color-title);
		text-transform: capitalize;
	}
	header,
	nav {
		flex-shrink: 0;
		width: 100%;
		background-color: var(--color-accent);
		box-sizing: border-box;
		left: 0;
		position: fixed;
		align-items: center;
		padding: 0 1rem;
		display: flex;
		z-index: 100;
		align-items: center;
		gap: 0rem;
	}

	main {
		padding-top: 80px;
		padding-bottom: 60px;
		min-height: 100dvh;
		box-sizing: border-box;
		background-color: var(--color-bg-dark);
	}

	nav {
		display: flex;
		bottom: 0;
		height: var(--nav-height);
		box-shadow: var(--shadow-up);
	}

	.nav-item,
	.more-menu-wrapper {
		display: flex;
		flex: 1;
		flex-direction: column;
		width: 70px;
		align-items: center;
		justify-content: center;
		text-decoration: none;
		position: relative;
		cursor: pointer;
		height: 100%;
		border: 0;
		color: var(--color-title);
		background: none;
		padding: 0;
		border: none;
		transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	}

	.nav-item:hover,
	.menu-popover-item:hover {
		filter: brightness(1.9);
		background-color: #ffffff1a;
	}

	.nav-item.active,
	.menu-popover-item.active {
		color: #ffffff;
		background: rgba(255, 255, 255, 0.05);
	}

	.nav-item.active::before {
		content: '';
		position: absolute;
		top: 0;
		width: 40%;
		height: 3px;
		background-color: var(--color-brand);
		border-radius: 0 0 4px 4px;
		box-shadow: var(--shadow-std);
	}

	.nav-item.active .label,
	.menu-popover-item.active .label {
		font-weight: 600;
	}

	.label {
		font-size: 0.85rem;
		font-family: 'URW Gothic', sans-serif;
		font-weight: 400;
		margin-top: 4px;
		letter-spacing: 0.05rem;
	}

	.backdrop {
		position: fixed;
		top: 0;
		left: 0;
		bottom: 60px;
		width: 100vw;
		height: calc(100dvh - 60px);
		background: rgba(0, 0, 0, 0.4);
		backdrop-filter: blur(2px);
		z-index: 999;
	}

	.menu-popover {
		position: absolute;
		bottom: 100%;
		right: 10px;

		background-color: var(--color-accent);
		border-radius: 12px 12px 0 0;
		box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);
		min-width: 140px;
		z-index: 1000;
		overflow: hidden;
	}

	.menu-popover-item {
		display: flex;
		align-items: center;
		gap: 12px;
		position: relative;
		min-height: 48px;
		padding: 12px 16px;
		text-decoration: none;
		color: var(--color-title);
	}

	.menu-popover-item.active::before {
		content: '';
		position: absolute;
		left: 0;
		top: 50%;
		transform: translateY(-50%);
		width: 4px;
		height: 60%;
		background-color: var(--color-brand);
		border-radius: 0 4px 4px 0;
		box-shadow: var(--shadow-right);
	}

	.viewport-guard {
		display: none;
	}

	@media (max-width: 319px) {
		.viewport-guard {
			display: block;
			position: fixed;
			text-align: center;
			font-family: 'URW Gothic', sans-serif;
			margin-top: 1rem;
			font-size: 1.2rem;
			color: var(--color-title);
		}

		.viewport-guard p {
			width: 90%;
			margin: auto;
			padding-top: 30px;
		}

		header,
		main,
		nav {
			display: none;
		}
	}
</style>
