<script setup lang="ts">
import { nextTick, ref, onMounted, useSlots } from 'vue'
import { useScrollHide } from '@/composables/useScrollHide'

import AppBar from './AppBar.vue'
import NavigationBar from './NavigationBar.vue'

const props = defineProps<{
	title: string
	noPadding?: boolean
}>()

const slots = useSlots()
const key =
	Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)

const pageContent = ref<HTMLElement | null>(null)
const appBar = ref<InstanceType<typeof AppBar> | null>(null)
const navBar = ref<InstanceType<typeof NavigationBar> | null>(null)

const announcePageChange = () => {
	const announcement = document.createElement('div')
	announcement.setAttribute('aria-live', 'polite')
	announcement.setAttribute('aria-atomic', 'true')
	announcement.className = 'sr-only'
	announcement.textContent = `Navigated to ${props.title}`
	document.body.appendChild(announcement)

	setTimeout(() => {
		document.body.removeChild(announcement)
	}, 1000)
}

onMounted(async () => {
	await nextTick()
	if (!pageContent.value) return

	const scrollHide = useScrollHide({
		scrollContainer: pageContent.value,
		appBarEl: appBar.value?.$el,
		navBarEl: navBar.value?.$el,
	})

	scrollHide.measureElements()
	scrollHide.attachScrollListener()

	const skipToContent = document.querySelector('#skip-to-content')
	if (document.activeElement === skipToContent) {
		pageContent.value.focus()
	} else {
		pageContent.value.setAttribute('tabindex', '-1')
		pageContent.value.focus()
	}

	announcePageChange()
})

const scrollToTop = (smooth = true) => {
	pageContent.value?.scrollTo({
		top: 0,
		behavior: smooth ? 'smooth' : 'instant',
	})
}

defineExpose({
	scrollToTop,
	scrollContainer: pageContent,
})
</script>

<template>
	<div class="page-layout" :id="key" :class="{ 'no-padding': noPadding }">
		<AppBar :title="title" ref="appBar">
			<template #content v-if="slots['app-bar']">
				<slot name="app-bar" />
			</template>
			<template #actions v-if="slots['actions']">
				<slot name="actions" />
			</template>
		</AppBar>
		<main class="page-content" ref="pageContent">
			<div class="content-container">
				<slot />
			</div>
		</main>
	</div>
</template>

<style scoped lang="scss">
@use '@/assets/variables.scss' as vars;

.page-layout {
	display: flex;
	flex-direction: column;
	max-height: 100%;
	height: 100%;
	overflow: hidden;
	background-color: hsl(var(--base));
	position: relative;
	margin: 0 auto;
	border: 1px solid transparent;
}

.page-content {
	flex: 1;
	-webkit-overflow-scrolling: touch;
	height: 100%;
	overflow-y: scroll;
	padding-top: calc(var(--inset-top, 0) + 4.5rem);

	display: flex;
	flex-direction: column;
	align-items: center;

	.content-container {
		width: 100%;
		max-width: 800px;
		padding: 0 1rem;

		h1,
		h2,
		h3,
		h4,
		h5,
		h6 {
			color: hsl(var(--text));
			margin-bottom: 0;
		}
		h1 {
			font-size: 2rem;
			font-weight: bolder;
		}
		h2 {
			font-size: 1.5rem;
			font-weight: bolder;
		}
	}
}

@media (min-width: 640px) {
	.page-layout {
		border-radius: 1rem;
		height: calc(100vh - 1rem);
		margin: 0.5rem;
		outline: 3px solid vars.$border-colour;
		outline-offset: -1px;
	}
}

.no-padding {
	.page-content {
		padding-top: calc(var(--inset-top, 0) + 3.5rem);
	}
	.content-container {
		padding: 0;
	}
}
</style>
