import * as plugins from './plugins.js';
import * as interfaces from './env.js';
// imports
import { CacheManager } from './classes.cachemanager.js';
import { Deferred } from '@push.rocks/smartpromise';
import { logger } from './logging.js';
// imported classes
import { UpdateManager } from './classes.updatemanager.js';
import { NetworkManager } from './classes.networkmanager.js';
import { TaskManager } from './classes.taskmanager.js';
import { ServiceworkerBackend } from './classes.backend.js';
import { getPersistentStore } from './classes.persistentstore.js';
export class ServiceWorker {
    // STATIC
    // INSTANCE
    serviceWindowRef;
    leleServiceWorkerBackend;
    cacheManager;
    updateManager;
    networkManager;
    taskManager;
    store;
    // TypedSocket connection for server communication
    typedsocket;
    typedrouter = new plugins.typedrequest.TypedRouter();
    handlersInitialized = false;
    constructor(selfArg) {
        logger.log('info', `Service worker instantiating at ${Date.now()}`);
        this.serviceWindowRef = selfArg;
        this.leleServiceWorkerBackend = new ServiceworkerBackend({
            self: selfArg,
            purgeCache: async (reqArg) => {
                await this.cacheManager.cleanCaches(),
                    logger.log('info', `cleaned caches in serviceworker as per request from frontend.`);
                return {};
            }
        });
        this.updateManager = new UpdateManager(this);
        this.networkManager = new NetworkManager(this);
        this.taskManager = new TaskManager(this);
        this.cacheManager = new CacheManager(this);
        this.store = new plugins.webstore.WebStore({
            dbName: 'losslessServiceworker',
            storeName: 'losslessServiceworker',
        });
        // =================================
        // Installation and Activation
        // =================================
        this.serviceWindowRef.addEventListener('install', async (event) => {
            const done = new Deferred();
            event.waitUntil(done.promise);
            // its important to not go async before event.waitUntil
            try {
                logger.log('success', `service worker installed! TimeStamp = ${new Date().toISOString()}`);
                // Log installation event
                const persistentStore = getPersistentStore();
                await persistentStore.init();
                await persistentStore.logEvent('sw_installed', 'Service worker installed', {
                    timestamp: new Date().toISOString(),
                });
                selfArg.skipWaiting();
                logger.log('note', `Called skip waiting!`);
                done.resolve();
            }
            catch (error) {
                logger.log('error', `Service worker installation error: ${error}`);
                done.reject(error);
            }
        });
        this.serviceWindowRef.addEventListener('activate', async (event) => {
            const done = new Deferred();
            event.waitUntil(done.promise);
            // its important to not go async before event.waitUntil
            try {
                await selfArg.clients.claim();
                logger.log('ok', 'Clients claimed successfully');
                await this.cacheManager.cleanCaches('new service worker loaded! :)');
                logger.log('ok', 'Caches cleaned successfully');
                // Log activation event
                const persistentStore = getPersistentStore();
                await persistentStore.init(); // Ensure store is initialized (safe to call multiple times)
                await persistentStore.logEvent('sw_activated', 'Service worker activated', {
                    timestamp: new Date().toISOString(),
                });
                done.resolve();
                logger.log('success', `Service worker activated at ${new Date().toISOString()}`);
                // Connect to TypedServer for cache invalidation after activation
                this.connectToServer();
            }
            catch (error) {
                logger.log('error', `Service worker activation error: ${error}`);
                done.reject(error);
            }
        });
        // Handle wake-up scenario: if already activated, connect immediately
        // (install/activate events don't fire on wake-up)
        if (selfArg.registration?.active) {
            logger.log('info', 'SW woke up (already activated) - connecting to server');
            this.connectToServer();
        }
    }
    /**
     * Initialize typed handlers (idempotent - safe to call multiple times)
     */
    initHandlers() {
        if (this.handlersInitialized)
            return;
        this.handlersInitialized = true;
        // Register handler for cache invalidation from server
        this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('serviceworker_cacheInvalidate', async (reqArg) => {
            logger.log('info', `Cache invalidation requested from server: ${reqArg.reason}`);
            // Log cache invalidation event (survives)
            const persistentStore = getPersistentStore();
            await persistentStore.init(); // Ensure store is initialized
            await persistentStore.logEvent('cache_invalidated', `Cache invalidated: ${reqArg.reason}`, {
                reason: reqArg.reason,
                timestamp: reqArg.timestamp,
            });
            // Reset cumulative metrics (they don't survive cache invalidation)
            await persistentStore.resetCumulativeMetrics();
            await this.cacheManager.cleanCaches(reqArg.reason);
            // Notify all clients to reload
            await this.leleServiceWorkerBackend.triggerReloadAll();
            return { success: true };
        }));
    }
    /**
     * Connect to TypedServer via TypedSocket for cache invalidation
     */
    async connectToServer() {
        try {
            this.initHandlers();
            // Connect to server via TypedSocket
            this.typedsocket = await plugins.typedsocket.TypedSocket.createClient(this.typedrouter, this.serviceWindowRef.location.origin);
            // Tag this connection as a service worker for server-side filtering
            await this.typedsocket.setTag('serviceworker', {});
            logger.log('ok', 'Service worker connected to TypedServer via TypedSocket');
        }
        catch (error) {
            logger.log('warn', `Service worker TypedSocket connection failed: ${error?.message || error}`);
            // Retry connection after a delay
            setTimeout(() => this.connectToServer(), 10000);
        }
    }
}
//# sourceMappingURL=data:application/json;base64, 