const CACHE_NAME = 'notes2-{{ .VERSION }}'
const CACHED_ASSETS = [
	'/',
	'/offline',

	'/css/{{ .VERSION }}/main.css',
	'/css/{{ .VERSION }}/markdown.css',
	'/css/{{ .VERSION }}/notes2.css',
	'/css/{{ .VERSION }}/theme.css',

	'/images/{{ .VERSION }}/collapsed.svg',
	'/images/{{ .VERSION }}/expanded.svg',
	'/images/{{ .VERSION }}/icon_history.svg',
	'/images/{{ .VERSION }}/icon_home.svg',
	'/images/{{ .VERSION }}/icon_markdown_hollow.svg',
	'/images/{{ .VERSION }}/icon_markdown.svg',
	'/images/{{ .VERSION }}/icon_refresh.svg',
	'/images/{{ .VERSION }}/icon_save_disabled.svg',
	'/images/{{ .VERSION }}/icon_save.svg',
	'/images/{{ .VERSION }}/icon_search.svg',
	'/images/{{ .VERSION }}/icon_settings.svg',
	'/images/{{ .VERSION }}/icon_table.svg',
	'/images/{{ .VERSION }}/leaf.svg',
	'/images/{{ .VERSION }}/logo_small.svg',
	'/images/{{ .VERSION }}/logo.svg',

	'/js/{{ .VERSION }}/api.mjs',
	'/js/{{ .VERSION }}/app.mjs',
	'/js/{{ .VERSION }}/checklist.mjs',
	'/js/{{ .VERSION }}/crypto.mjs',
	'/js/{{ .VERSION }}/file.mjs',
	'/js/{{ .VERSION }}/key.mjs',
	'/js/{{ .VERSION }}/lib/css_colorize.mjs',
	'/js/{{ .VERSION }}/lib/custom_html_element.mjs',
	'/js/{{ .VERSION }}/lib/node_modules/marked/lib/marked.esm.js',
	'/js/{{ .VERSION }}/lib/node_modules/marked-token-position/lib/index.esm.js',
	'/js/{{ .VERSION }}/lib/sjcl.js',
	'/js/{{ .VERSION }}/marked_position.mjs',
	'/js/{{ .VERSION }}/mbus.mjs',
	'/js/{{ .VERSION }}/node_store.mjs',
	'/js/{{ .VERSION }}/notes2.mjs',
	'/js/{{ .VERSION }}/page_history.mjs',
	'/js/{{ .VERSION }}/page_node.mjs',
	'/js/{{ .VERSION }}/page_storage.mjs',
	'/js/{{ .VERSION }}/sync.mjs',
	'/js/{{ .VERSION }}/tree.mjs',
]

async function precache() {
	const cache = await caches.open(CACHE_NAME)
	return cache.addAll(CACHED_ASSETS)
}

async function fetchAsset(event) {
	try {
		const cache = await caches.open(CACHE_NAME)
		const match = await cache.match(event.request)

		if (match !== undefined) {
			// -----------------------------------------------
			// This page is precached - return it immediately.
			// -----------------------------------------------
			console.debug('From cache', event.request.url)
			return match
		} else {
			// ---------------------------------------------------------------
			// Not in cache - send it for an online request/browser cache hit.
			// ---------------------------------------------------------------
			console.debug('From network', event.request.url)
			const resp = await fetch(event.request)

			// This will trigger on an HTTP error such as 502.
			if (!resp.ok) {
				console.error('HTTP error', resp.status)

				// When JSON is expected, return that instead of the offline HTML page.
				return await offline(event, `${resp.status} ${resp.statusText}`)
			}
			return resp
		}
	} catch (e) {
		// An error here is something like a DNS problem, not a regular HTTP problem.
		console.error('Network error', e, event.request.url)
		return await offline(event, e)
	}
}

async function offline(event, errText) {
	if (event.request.headers.get('X-JSON')) {
		return new Response('{ "OK": false, "Error": "Network is offline"}', { headers: { 'Content-Type': 'application/json' } })
	}

	const cache = await caches.open(CACHE_NAME)
	const offline = await cache.match('/offline')
	let body = await offline.text()
	body = body.replace('||ERROR||', errText)
	return new Response(body, { headers: { 'Content-Type': 'text/html' } })
}

async function cleanupCache() {
	const keys = await caches.keys()
	const keysToDelete = keys.map(key => {
		if (key !== CACHE_NAME)
			return caches.delete(key)
	})
	return Promise.all(keysToDelete)
}

self.addEventListener('install', event => {
	console.debug('SERVICE WORKER: install')
	self.skipWaiting()
	event.waitUntil(precache())
})

self.addEventListener('activate', event => {
	console.debug('SERVICE WORKER: activate')
	self.clients.claim()
	event.waitUntil(cleanupCache())
})

self.addEventListener('fetch', event => {
	// console.debug('SERVICE WORKER: fetch', event.request.url)

	if ({{ .DevMode }})
		return event

	event.respondWith(fetchAsset(event))
})
