globalThis.Wegwichtel = globalThis.Wegwichtel || {}; (function (ns) { 'use strict'; const PRIVACY_KEY = 'wegwichtel.privacy.v1'; const PROGRESS_KEY = 'wegwichtel.route-progress.v1'; const MAX_PROGRESS_AGE_MS = 24 * 60 * 60 * 1000; function storage() { try { return globalThis.localStorage ?? null; } catch { return null; } } function now() { return Date.now(); } function readJson(key, fallback) { const store = storage(); if (!store) return fallback; try { const raw = store.getItem(key); if (!raw) return fallback; const value = JSON.parse(raw); return value && typeof value === 'object' ? value : fallback; } catch { return fallback; } } function writeJson(key, value) { const store = storage(); if (!store) return false; try { store.setItem(key, JSON.stringify(value)); return true; } catch { return false; } } function removeItem(key) { const store = storage(); if (!store) return false; try { store.removeItem(key); return true; } catch { return false; } } function normalizeSettings(value) { return { progressStorage: value?.progressStorage === true, cookies: false, updatedAt: Number(value?.updatedAt) || now() }; } function readSettings() { return normalizeSettings(readJson(PRIVACY_KEY, {})); } function writeSettings(settings) { return writeJson(PRIVACY_KEY, normalizeSettings({ ...settings, updatedAt: now() })); } function isProgressStorageEnabled() { return readSettings().progressStorage === true; } function setProgressStorageEnabled(enabled) { const nextValue = Boolean(enabled); writeSettings({ progressStorage: nextValue, cookies: false }); if (!nextValue) removeItem(PROGRESS_KEY); return nextValue; } function cookiesEnabled() { return false; } function routeId(route) { const id = route?.id ?? route?.routeId ?? route; return id === null || id === undefined ? null : String(id); } function asNumberOrNull(value) { const number = Number(value); return Number.isFinite(number) ? number : null; } function numericIdSet(values) { if (!Array.isArray(values)) return []; return [...new Set(values.map(Number).filter(Number.isFinite))]; } function readProgressStore() { const data = readJson(PROGRESS_KEY, {}); const entries = data?.routes && typeof data.routes === 'object' ? data.routes : data; return entries && typeof entries === 'object' ? entries : {}; } function writeProgressStore(routes) { return writeJson(PROGRESS_KEY, { version: 1, updatedAt: now(), routes }); } function normalizeSavedRouteState(value) { if (!value || typeof value !== 'object') return null; return { routeId: value.routeId === null || value.routeId === undefined ? null : String(value.routeId), routeState: value.routeState === 'running' || value.routeState === 'paused' ? value.routeState : 'idle', routeProgressIndex: Number.isInteger(value.routeProgressIndex) ? value.routeProgressIndex : null, visitedPoiIds: numericIdSet(value.visitedPoiIds), viewedPoiIds: numericIdSet(value.viewedPoiIds), playedAudioPoiIds: numericIdSet(value.playedAudioPoiIds), savedAt: Number(value.savedAt) || Number(value.updatedAt) || 0, updatedAt: Number(value.updatedAt) || Number(value.savedAt) || 0 }; } function isExpired(value, referenceTime = now()) { const saved = Number(value?.updatedAt) || Number(value?.savedAt) || 0; return saved <= 0 || referenceTime - saved > MAX_PROGRESS_AGE_MS; } function saveRouteState(route, routeState, routeProgressIndex, visitedPoiIds = [], viewedPoiIds = [], playedAudioPoiIds = []) { if (!isProgressStorageEnabled()) return false; const id = routeId(route); if (!id) return false; const routes = readProgressStore(); const timestamp = now(); routes[id] = { routeId: id, routeName: route?.name ?? '', routeState: routeState === 'running' || routeState === 'paused' ? routeState : 'idle', routeProgressIndex: Number.isInteger(routeProgressIndex) ? routeProgressIndex : null, visitedPoiIds: numericIdSet(visitedPoiIds), viewedPoiIds: numericIdSet(viewedPoiIds), playedAudioPoiIds: numericIdSet(playedAudioPoiIds), savedAt: timestamp, updatedAt: timestamp }; return writeProgressStore(routes); } function activateRoute(route) { if (!isProgressStorageEnabled()) return null; const id = routeId(route); if (!id) return null; const routes = cleanupExpiredEntries().routes; const saved = normalizeSavedRouteState(routes[id]); return saved && !isExpired(saved) ? saved : null; } function cleanupExpiredEntries(progressCallback) { const referenceTime = now(); const routes = readProgressStore(); const entries = Object.entries(routes); const kept = {}; let removed = 0; entries.forEach(([id, value], index) => { const normalized = normalizeSavedRouteState(value); if (normalized && !isExpired(normalized, referenceTime)) kept[id] = normalized; else removed += 1; reportCleanupProgress(progressCallback, index + 1, entries.length, removed); }); if (removed > 0) writeProgressStore(kept); return { removed, total: entries.length, routes: kept }; } function reportCleanupProgress(callback, processed, total, removed) { if (typeof callback !== 'function') return; callback({ processed, total, removed }); } async function cleanupExpiredProgress(progressCallback) { return cleanupExpiredEntries(progressCallback); } ns.PrivacyStorage = Object.freeze({ PRIVACY_KEY, PROGRESS_KEY, MAX_PROGRESS_AGE_MS, activateRoute, cleanExpiredProgress: cleanupExpiredProgress, cleanupExpiredProgress, cookiesEnabled: () => false, getPrivacySettings: readSettings, isProgressStorageEnabled, removeExpiredProgress: cleanupExpiredProgress, removeExpiredRouteProgress: cleanupExpiredProgress, saveRouteState, setProgressStorageEnabled }); }(globalThis.Wegwichtel));