// This is the AlekSIS service worker

const CACHE = "aleksis-cache";

const cacheChannel = new BroadcastChannel("cache-or-not");
const offlineFallbackChannel = new BroadcastChannel("offline-fallback");

let comesFromCache = false;
let offlineFallback = false;

self.addEventListener("install", function (event) {
  console.log("[AlekSIS PWA] Install Event processing.");

  console.log("[AlekSIS PWA] Skipping waiting on install.");
  self.skipWaiting();
});

// Allow sw to control of current page
self.addEventListener("activate", function (event) {
  console.log("[AlekSIS PWA] Claiming clients for current page.");
  event.waitUntil(self.clients.claim());
});

// If any fetch fails, it will look for the request in the cache and serve it from there first
self.addEventListener("fetch", function (event) {
  if (event.request.method !== "GET") return;
  networkFirstFetch(event);
  if (offlineFallback) offlineFallbackChannel.postMessage(true);
  if (comesFromCache) cacheChannel.postMessage(true);
});

function networkFirstFetch(event) {
  event.respondWith(
    fetch(event.request)
      .then(function (response) {
        // If request was successful, add or update it in the cache
        console.log("[AlekSIS PWA] Network request successful.");
        event.waitUntil(updateCache(event.request, response.clone()));
        offlineFallback = false;
        comesFromCache = false;
        return response;
      })
      .catch(function (error) {
        console.log(
          "[AlekSIS PWA] Network request failed. Serving content from cache: " +
            error
        );
        return fromCache(event);
      })
  );
}

function fromCache(event) {
  // Check to see if you have it in the cache
  // Return response
  // If not in the cache, then return offline fallback page
  return caches.open(CACHE).then(function (cache) {
    return cache.match(event.request).then(function (matching) {
      if (!matching || matching.status === 404) {
        console.log(
          "[AlekSIS PWA] Cache request failed. Serving offline fallback page."
        );
        comesFromCache = false;
        offlineFallback = true;
        return;
      }
      offlineFallback = false;
      comesFromCache = true;
      return matching;
    });
  });
}

function updateCache(request, response) {
  if (
    response.headers.get("cache-control") &&
    response.headers.get("cache-control").includes("no-cache")
  ) {
    return Promise.resolve();
  } else {
    return caches.open(CACHE).then(function (cache) {
      return cache.put(request, response);
    });
  }
}
