const CACHE = 'dashcaddy-shell-43a872cc40';
const PRECACHE = [
  '/',
  '/index.html',
  '/css/themes.css',
  '/css/dashboard.css',
  '/css/driver.min.css',
  '/css/onboarding.css',
  '/dist/core.js',
  '/dist/features.js',
  '/dist/init.js',
  '/dist/onboarding.js',
  '/assets/fonts.css',
  '/assets/site.webmanifest',
  '/assets/favicon.svg',
  '/assets/dashcaddy-favicon.ico',
  '/assets/icon-192.png',
  '/assets/icon-512.png',
  '/assets/apple-touch-icon.png',
  '/assets/dashcaddy-logo-dark.png',
  '/assets/dashcaddy-logo-light.png',
  '/assets/sami7777-logo.png',
  '/assets/fonts/sami-grotesk/SamiGrotesk-Regular.woff2',
  '/assets/fonts/sami-grotesk/SamiGrotesk-Medium.woff2',
  '/assets/fonts/sami-grotesk/SamiGrotesk-Bold.woff2',
  '/assets/fonts/DSEG7Classic-Bold.woff2',
  '/assets/weather/clear-day.svg',
  '/assets/weather/clear-night.svg',
  '/assets/weather/partly-cloudy-day.svg',
  '/assets/weather/partly-cloudy-night.svg',
  '/assets/weather/cloudy.svg',
  '/assets/weather/fog.svg',
  '/assets/weather/drizzle.svg',
  '/assets/weather/rain.svg',
  '/assets/weather/sleet.svg',
  '/assets/weather/snow.svg',
  '/assets/weather/thunderstorm.svg',
  '/assets/weather/wind.svg'
];

function isNavigationRequest(request) {
  return request.mode === 'navigate';
}

function isStaticAsset(pathname) {
  return pathname.startsWith('/assets/')
    || pathname.startsWith('/css/')
    || pathname.startsWith('/dist/');
}

async function networkFirst(request, preloadResponsePromise) {
  const cache = await caches.open(CACHE);
  try {
    const preloadResponse = preloadResponsePromise ? await preloadResponsePromise : null;
    if (preloadResponse) {
      cache.put(request, preloadResponse.clone()).catch(() => {});
      return preloadResponse;
    }
    const response = await fetch(request);
    cache.put(request, response.clone()).catch(() => {});
    return response;
  } catch (_) {
    return caches.match(request) || caches.match('/index.html');
  }
}

async function staleWhileRevalidate(request) {
  const cache = await caches.open(CACHE);
  const cached = await cache.match(request);

  const networkPromise = fetch(request)
    .then((response) => {
      cache.put(request, response.clone()).catch(() => {});
      return response;
    })
    .catch(() => null);

  if (cached) return cached;
  return networkPromise.then((response) => response || Response.error());
}

self.addEventListener('install', (event) => {
  self.skipWaiting();
  event.waitUntil(
    caches.open(CACHE).then((cache) =>
      cache.addAll(PRECACHE.map((url) => new Request(url, { cache: 'reload' })))
    )
  );
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    const keys = await caches.keys();
    await Promise.all(keys.filter((key) => key !== CACHE).map((key) => caches.delete(key)));
    if ('navigationPreload' in self.registration) {
      await self.registration.navigationPreload.enable();
    }
    await self.clients.claim();
  })());
});

self.addEventListener('fetch', (event) => {
  const { request } = event;
  if (request.method !== 'GET') return;

  const url = new URL(request.url);
  if (url.origin !== self.location.origin) return;
  if (url.pathname.startsWith('/api/v1/') || url.pathname.startsWith('/probe/')) return;

  if (isNavigationRequest(request) || url.pathname === '/' || url.pathname.endsWith('/index.html')) {
    event.respondWith(networkFirst(request, event.preloadResponse));
    return;
  }

  if (isStaticAsset(url.pathname)) {
    event.respondWith(staleWhileRevalidate(request));
  }
});
