const debugLog = false;
// Establish a cache name
const cacheName = "dandelion_cache_v1";

const contentToCache = [
  '/static/index.html',
  '/static/main.css',
  '/static/main2.js',
  '/static/lib/marked.min.js',
  '/static/lib/qrcode.min.js',
  '/static/db.js',
  '/static/PeerManager.js',
  '/static/IDUtils.js',
  '/static/dataUtils.js',
  '/static/App.js',
  '/static/Sync.js',
  '/static/IDUtils.js',
  '/static/log.js',
  '/static/favicon.ico'
];

self.addEventListener("install", (e: any) => {
  e.waitUntil(
    (async () => {
      const cache = await caches.open(cacheName);
      console.log(
        "[Service Worker] Caching all: app shell and content",
        contentToCache
      );

      try {
        await cache.addAll(contentToCache);
      } catch (e) {
        debugLog ? console.log(e) : null;
      }
    })()
  );
});


async function staleWhileRevalidate(event: any) {

  let cache = await caches.open(cacheName);

  let response = await cache.match(event.request);

  if (response) {
    debugLog ? console.log('Service Worker: Cache hit', event.request.url) : null;
  }

  const fetchPromise = (async () => {
    debugLog ? console.log('Service Worker: Fetching', event.request.url) : null;

    let networkResponse = null;
    try {
      networkResponse = await fetch(event.request);
    } catch (e) {
      debugLog ? console.log('Service Worker: Failed to fetch', e) : null;

      return new Response('Network error occurred', {
        status: 404,
        statusText: 'Cache miss and fetch failed',
        headers: { 'Content-Type': 'text/plain' }
      });
    }

    debugLog ? console.log('Service Worker: Updating cache', event.request.url) : null;

    try {
      await cache.put(event.request, networkResponse.clone());
    } catch (e) {
      debugLog ? console.log('Service Worker: failed to update cache', event.request.url, e) : null;

    }

    debugLog ? console.log('Service Worker: Returning networkResponse', event.request.url) : null;
    return networkResponse;
  })();


  debugLog ? console.log('Service Worker: Returning return response || fetchPromise', event.request.url) : null;
  return response || fetchPromise;

  // if (networkResponse) {
  //   cache.put(event.request, networkResponse.clone())
  //   return networkResponse;
  // }



  // caches.open(cacheName)
  //   .then(function (cache) {
  //     return cache.match(event.request)
  //       .then(function (response) {
  //         var fetchPromise = fetch(event.request)
  //           .then(function (networkResponse) {
  //             cache.put(event.request, networkResponse.clone());
  //             return networkResponse;
  //           });
  //         return response || fetchPromise;
  //       });
  //   })
}

// async function responder(event: any) {
//   debugLog ? console.log('Fetching', event.request.url) : null;

//   let response = await fetch(event.request);

//   if (!response) {
//     debugLog ? console.log('Fetch failed, falling back to cache', event.request.url) : null;
//     let cacheMatch = await caches.match(event.request);
//     if (!cacheMatch) {
//       // DUnno what to return here!
//     }
//     return cacheMatch;
//   }

//   if (response.status === 206) {
//     debugLog ? console.log('Not caching partial content') : null;
//     return response;
//   }

//   debugLog ? console.log('Fetch successful, updating cache', event.request.url) : null;
//   const cache = await caches.open(cacheName);
//   try {
//     cache.put(event.request, response.clone()).catch((error) => debugLog ? console.log('failed to cache', event.request, error)) : null;
//   } catch (e) {
//     console.log('failed to cache', event.request)
//   }
//   return response;
// }

self.addEventListener('fetch', function (event: any) {
  event.respondWith(staleWhileRevalidate(event));
  // event.respondWith(responder(event));
});

addEventListener("message", async (e) => {
  debugLog ? console.log(`Message received:`, e.data) : null;

  switch (e.data.type) {
    case "update_app":
      const cache = await caches.open(cacheName);
      debugLog ? console.log(`[Service Worker] Caching resources`) : null;
      // cache.put("/main.js", new Response());

      for (let item of contentToCache) {
        cache.delete(item);
      }

      await cache.addAll(contentToCache);
      break;
  }
});
