"use strict";const OFFLINE_DATA_FILE="offline.json",CACHE_NAME_PREFIX="c3offline",BROADCASTCHANNEL_NAME="offline",CONSOLE_PREFIX="[SW] ",LAZYLOAD_KEYNAME="",broadcastChannel="undefined"==typeof BroadcastChannel?null:new BroadcastChannel("offline");class PromiseThrottle{constructor(e){this._maxParallel=e,this._queue=[],this._activeCount=0}Add(e){return new Promise(((t,a)=>{this._queue.push({func:e,resolve:t,reject:a}),this._MaybeStartNext()}))}async _MaybeStartNext(){if(!this._queue.length||this._activeCount>=this._maxParallel)return;this._activeCount++;const e=this._queue.shift();try{const t=await e.func();e.resolve(t)}catch(t){e.reject(t)}this._activeCount--,this._MaybeStartNext()}}const networkThrottle=new PromiseThrottle(20);function PostBroadcastMessage(e){broadcastChannel&&setTimeout((()=>broadcastChannel.postMessage(e)),3e3)}function Broadcast(e){PostBroadcastMessage({"type":e})}function BroadcastDownloadingUpdate(e){PostBroadcastMessage({"type":"downloading-update","version":e})}function BroadcastUpdateReady(e){PostBroadcastMessage({"type":"update-ready","version":e})}function IsUrlInLazyLoadList(e,t){if(!t)return!1;try{for(const a of t)if(new RegExp(a).test(e))return!0}catch(e){console.error("[SW] Error matching in lazy-load list: ",e)}return!1}function WriteLazyLoadListToStorage(e){return"undefined"==typeof localforage?Promise.resolve():localforage.setItem("",e)}function ReadLazyLoadListFromStorage(){return"undefined"==typeof localforage?Promise.resolve([]):localforage.getItem("")}function GetCacheBaseName(){return"c3offline-"+self.registration.scope}function GetCacheVersionName(e){return GetCacheBaseName()+"-v"+e}async function GetAvailableCacheNames(){const e=await caches.keys(),t=GetCacheBaseName();return e.filter((e=>e.startsWith(t)))}async function IsUpdatePending(){return(await GetAvailableCacheNames()).length>=2}async function GetMainPageUrl(){const e=await clients.matchAll({includeUncontrolled:!0,type:"window"});for(const t of e){let e=t.url;if(e.startsWith(self.registration.scope)&&(e=e.substring(self.registration.scope.length)),e&&"/"!==e)return e.startsWith("?")&&(e="/"+e),e}return""}function fetchWithBypass(e,t){return"string"==typeof e&&(e=new Request(e)),t?fetch(e.url,{headers:e.headers,mode:e.mode,credentials:e.credentials,redirect:e.redirect,cache:"no-store"}):fetch(e)}async function CreateCacheFromFileList(e,t,a){const n=await Promise.all(t.map((e=>networkThrottle.Add((()=>fetchWithBypass(e,a))))));let o=!0;for(const e of n)e.ok||(o=!1,console.error("[SW] Error fetching '"+e.url+"' ("+e.status+" "+e.statusText+")"));if(!o)throw new Error("not all resources were fetched successfully");const s=await caches.open(e);try{return await Promise.all(n.map(((e,a)=>s.put(t[a],e))))}catch(t){throw console.error("[SW] Error writing cache entries: ",t),caches.delete(e),t}}async function UpdateCheck(e){try{const t=await fetchWithBypass("offline.json",!0);if(!t.ok)throw new Error("offline.json responded with "+t.status+" "+t.statusText);const a=await t.json(),n=a.version,o=a.fileList,s=a.lazyLoad,r=GetCacheVersionName(n);if(await caches.has(r)){return void(await IsUpdatePending()?(console.log("[SW] Update pending"),Broadcast("update-pending")):(console.log("[SW] Up to date"),Broadcast("up-to-date")))}const i=await GetMainPageUrl();o.unshift("./"),i&&-1===o.indexOf(i)&&o.unshift(i),console.log("[SW] Caching "+o.length+" files for offline use"),e?Broadcast("downloading"):BroadcastDownloadingUpdate(n),s&&await WriteLazyLoadListToStorage(s),await CreateCacheFromFileList(r,o,!e);await IsUpdatePending()?(console.log("[SW] All resources saved, update ready"),BroadcastUpdateReady(n)):(console.log("[SW] All resources saved, offline support ready"),Broadcast("offline-ready"))}catch(e){console.warn("[SW] Update check failed: ",e)}}async function GetCacheNameToUse(e,t){if(1===e.length||!t)return e[0];if((await clients.matchAll()).length>1)return e[0];const a=e[e.length-1];return console.log("[SW] Updating to new version"),await Promise.all(e.slice(0,-1).map((e=>caches.delete(e)))),a}async function HandleFetch(e,t){const a=await GetAvailableCacheNames();if(!a.length)return fetch(e.request);const n=await GetCacheNameToUse(a,t),o=await caches.open(n),s=await o.match(e.request);if(s)return s;const r=await Promise.all([fetch(e.request),ReadLazyLoadListFromStorage()]),i=r[0],c=r[1];if(IsUrlInLazyLoadList(e.request.url,c))try{await o.put(e.request,i.clone())}catch(t){console.warn("[SW] Error caching '"+e.request.url+"': ",t)}return i}self.addEventListener("install",(e=>{e.waitUntil(UpdateCheck(!0).catch((()=>null)))})),self.addEventListener("fetch",(e=>{if(new URL(e.request.url).origin!==location.origin)return;const t="navigate"===e.request.mode,a=HandleFetch(e,t);t&&e.waitUntil(a.then((()=>UpdateCheck(!1)))),e.respondWith(a)}));