/* Service worker
   - App code (html/css/app js)  → network-first  (a plain refresh shows updates)
   - Libs / fonts / icons / images → cache-first    (immutable, load fast)
   - Map tiles (OSM)              → stale-while-revalidate (offline map)
   - API (Objects/Report/…)       → network-first, cache fallback
*/
var VERSION = 'v14';
var SHELL_CACHE = 'inspector-shell-' + VERSION;
var TILE_CACHE = 'inspector-tiles';           // kept across versions
var TILE_MAX = 600;

var SHELL = [
    './', './index.html', './manifest.webmanifest',
    './css/app.css', './css/all.min.css',
    './js/lib/vue.min.js', './js/lib/axios.min.js', './js/lib/bootstrap.bundle.min.js', './js/lib/toast.js',
    './js/lib/markerclusterer.js',
    './js/theme.js', './js/ptr.js', './js/config.js', './js/gmap.js', './js/api.js', './js/data.js', './js/mock.js', './js/app.js',
    './js/views/common.js', './js/views/media.js', './js/views/objects.js', './js/views/object-detail.js', './js/views/search.js',
    './js/views/new-object.js', './js/views/registries.js', './js/views/map.js', './js/views/gis.js',
    './icons/fhn-192.png', './icons/fhn-512.png', './icons/fhn-maskable-512.png', './assets/fhn-logo.png'
];

self.addEventListener('install', function (e) {
    e.waitUntil(caches.open(SHELL_CACHE).then(function (c) { return c.addAll(SHELL); }).then(function () { return self.skipWaiting(); }));
});

self.addEventListener('activate', function (e) {
    e.waitUntil(caches.keys().then(function (keys) {
        return Promise.all(keys.filter(function (k) { return k !== SHELL_CACHE && k !== TILE_CACHE; }).map(function (k) { return caches.delete(k); }));
    }).then(function () { return self.clients.claim(); }));
});

function isImmutable(p) { return /\/(webfonts|icons|assets)\//.test(p) || /\/js\/lib\//.test(p) || /\/css\/(ol|all\.min)/.test(p); }
function isApi(p) { return /\/(Objects|Report|Reviews|Settings|Account)\//i.test(p); }
function isTile(host) { return /server\.arcgisonline\.com$|tile\.openstreetmap\.org$|basemaps\.cartocdn\.com$/.test(host); }

self.addEventListener('fetch', function (e) {
    var req = e.request;
    if (req.method !== 'GET') return;
    var url = new URL(req.url);

    // Map tiles (cross-origin) → stale-while-revalidate, capped cache
    if (isTile(url.hostname)) {
        e.respondWith(caches.open(TILE_CACHE).then(function (cache) {
            return cache.match(req).then(function (hit) {
                var net = fetch(req).then(function (res) {
                    if (res && res.status === 200) { cache.put(req, res.clone()); trimCache(TILE_CACHE, TILE_MAX); }
                    return res;
                }).catch(function () { return hit; });
                return hit || net;
            });
        }));
        return;
    }

    if (url.origin !== location.origin) return;   // other cross-origin: let it pass

    // API → network-first
    if (isApi(url.pathname)) {
        e.respondWith(fetch(req).catch(function () { return caches.match(req); }));
        return;
    }

    // Immutable assets → cache-first
    if (isImmutable(url.pathname)) {
        e.respondWith(caches.match(req).then(function (hit) {
            return hit || fetch(req).then(function (res) { return cachePut(SHELL_CACHE, req, res); });
        }));
        return;
    }

    // App code (html/css/js) → network-first, cache fallback
    e.respondWith(
        fetch(req).then(function (res) { return cachePut(SHELL_CACHE, req, res); })
            .catch(function () { return caches.match(req).then(function (h) { return h || caches.match('./index.html'); }); })
    );
});

function cachePut(name, req, res) {
    if (res && res.status === 200 && res.type === 'basic') {
        var copy = res.clone();
        caches.open(name).then(function (c) { c.put(req, copy); });
    }
    return res;
}

function trimCache(name, max) {
    caches.open(name).then(function (c) {
        c.keys().then(function (keys) { if (keys.length > max) c.delete(keys[0]); });
    });
}
