<script>
import { defineAsyncComponent } from 'vue';
import Project from '@components/project';

const aoRoutes = {
	'project': Project, //Merge app.js and project.js calls to avoid extra http request on inital page
	'admin': defineAsyncComponent(() => import(/* webpackChunkName: "admin" */ '@components/admin')),
	'upload': defineAsyncComponent(() => import(/* webpackChunkName: "upload" */ '@components/upload'))
};

export default {
	data() {
		return {
			hash: {page: '', items: [], prev: {}},
			consts: this.appConfig.consts,
			mobile: false
		};
	},
	provide() {
		return {
			hash: this.hash,
			consts: this.consts,
			isMobile: () => this.isMobile(),
			getAnchor: this.getAnchor,
			getPrevAnchor: () => this.getPrevAnchor(),
		};
	},
	computed: {
		route() {
			return aoRoutes[this.hash.page];
		},
		hashSnapshot() {
			const { prev, ...asHash } = this.hash;
			return JSON.stringify(asHash);
		}
	},
	inject: ['appConfig'],
	created() {
		this.mobileMediaQuery = window.matchMedia('only screen and (max-width: 800px)');
		this.mobileMediaQuery.addEventListener('change', this.updateMobile);
		this.updateMobile();

		//Set initial page
		this.setVarHash(this.validateRoute(this.getBrowserHash()));
	},
	mounted() {
		//Catch browser hash change
		window.addEventListener('hashchange', this.onBrowserHashChange);
	},
	watch: {
		hashSnapshot(jNewHash, jOldHash) {
			const asNewHash = this.validateRoute(JSON.parse(jNewHash));

			//Sync variable -> #hash
			if(asNewHash != this.getBrowserHash()) {
				this.setBrowserHash(asNewHash.page, asNewHash.items);
			}

			//Store previous value
			this.hash.prev = JSON.parse(jOldHash);

			this.setPageTitle(asNewHash.page);
		}
	},
	methods: {
		isMobile() {
			return this.mobile;
		},
		updateMobile() {
			this.mobile = this.mobileMediaQuery.matches;
		},
		setPageTitle(sTitle) {
			document.title = this.consts.title + ' - ' + sTitle.trim();
		},
		setVarHash(asHash) {
			this.hash.page = asHash.page || '';
			this.hash.items = Array.isArray(asHash.items) ? [...asHash.items.filter(n => n)] : [];
		},
		onBrowserHashChange() { //Sync #hash -> variable
			let asHash = this.getBrowserHash();
			if(asHash != this.hash) this.setVarHash(asHash);
		},
		getBrowserHash() {
			let sHash = window.location.hash.slice(1);
			let asHash = sHash.split(this.consts.hash_sep).filter(n => n);
			let sPage = asHash.shift() || '';
			return {page: sPage, items: asHash};
		},
		setBrowserHash(sPage = '', asItems = []) {
			if(typeof asItems == 'string' && asItems != '') asItems = [asItems];
			window.location.hash = this.getAnchor([sPage, ...asItems]);
		},
		getAnchor(asBreadCrumbs) {
			return '#' + asBreadCrumbs.filter(Boolean).join(this.consts.hash_sep);
		},
		getPrevAnchor() {
			return this.getAnchor([this.hash.prev.page, ...this.hash.prev.items]);
		},
		validateRoute(asHash) {
			if(!Object.keys(aoRoutes).includes(asHash.page)) asHash.page = this.consts.default_page;
			return asHash;
		}
	},
	beforeUnmount() {
		window.removeEventListener('hashchange', this.onBrowserHashChange);
		this.mobileMediaQuery.removeEventListener('change', this.updateMobile);
	}
}
</script>
<template>
	<div id="main">
		<component :is="route" />
	</div>
</template>	
