/// <reference lib="WebWorker" />


declare const buildOutput: string[]

// declare const globalThis: ServiceWorkerGlobalScope
declare const skipWaiting: ServiceWorkerGlobalScope['skipWaiting']
declare const clients: Clients
// declare const addEventListener: ServiceWorkerGlobalScope['addEventListener']

type AddEvent = ServiceWorkerGlobalScope['addEventListener']


const assetsSet: Set<string> = new Set()
// generated by serviceworker-webpack-plugin

buildOutput.forEach(asset => {
    assetsSet.add(`${origin}/${asset}`)
})


const cacheURLRegExp = /^http.*\.(woff2|png|jpg|ico|css|js|json)/
const cacheMethod = 'GET'
const isCachable = (req: Request) => {
    const { url, method } = req
    return method == cacheMethod && cacheURLRegExp.test(url)
}

async function processRequest(req: Request) {
    const cachedResp = await caches.match(req)

    if (cachedResp) return cachedResp
    else try {
        const res = await fetch(req)
        if (res.ok) {
            const clonedRes = res.clone()
            caches.open(req.url)
                .then(cache => cache.put(req, clonedRes))

            return res
        }
    } catch (e) { console.error(e) }
}


(addEventListener as AddEvent)('fetch', e => {
    const req = e.request
    // @ts-ignore
    isCachable(req) && e.respondWith( processRequest(req) )
})

;(addEventListener as AddEvent)('activate', e => {
    async function preCache() {
        const cachesKeys = await caches.keys()
        cachesKeys.forEach(cacheName => {
            assetsSet.has(cacheName) || caches.delete(cacheName)
        })

        const cachesKeysSet = new Set(cachesKeys)
        assetsSet.forEach(async asset => {
            if (!cachesKeysSet.has(asset)) {
                const cache = await caches.open(asset)
                cache.add(asset)
            }
        })
    }


    e.waitUntil(preCache())
    e.waitUntil(clients.claim())
})

;(addEventListener as AddEvent)('install', () => {
    skipWaiting()
})