"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "PrinterSocketStore", {
    enumerable: true,
    get: function() {
        return PrinterSocketStore;
    }
});
const _node = require("@sentry/node");
const _errorutils = require("../utils/error.utils");
const _eventconstants = require("../constants/event.constants");
const _printerapiinterface = require("../services/printer-api.interface");
class PrinterSocketStore {
    socketFactory;
    eventEmitter2;
    printerCache;
    printerSocketAdaptersById = new Map();
    logger;
    constructor(loggerFactory, socketFactory, eventEmitter2, printerCache){
        this.socketFactory = socketFactory;
        this.eventEmitter2 = eventEmitter2;
        this.printerCache = printerCache;
        this.logger = loggerFactory(PrinterSocketStore.name);
        this.subscribeToEvents();
    }
    getSocketStatesById() {
        const socketStatesById = {};
        this.printerSocketAdaptersById.forEach((s)=>{
            if (!s.printerId) {
                return;
            }
            socketStatesById[s.printerId] = {
                printerId: s.printerId,
                printerType: s.printerType,
                socket: s.socketState,
                api: s.apiState
            };
        });
        return socketStatesById;
    }
    async loadPrinterSockets() {
        await this.printerCache.loadCache();
        const printerDtoList = await this.printerCache.listCachedPrinters(false);
        this.printerSocketAdaptersById.clear();
        for (const printerDto of printerDtoList){
            try {
                this.createOrUpdateSocket(printerDto);
            } catch (e) {
                (0, _node.captureException)(e);
                this.logger.error("PrinterSocketStore failed to construct new socket.", (0, _errorutils.errorSummary)(e));
            }
        }
        this.logger.log(`Loaded ${this.printerSocketAdaptersById.size} printer sockets`);
    }
    listPrinterSockets() {
        return Array.from(this.printerSocketAdaptersById.values());
    }
    reconnectPrinterAdapter(id) {
        const socket = this.getPrinterSocket(id);
        if (!socket) return;
        socket.close();
        socket.resetSocketState();
    }
    getPrinterSocket(id) {
        return this.printerSocketAdaptersById.get(id);
    }
    async reconnectPrinterSockets() {
        let reauthRequested = 0;
        let socketSetupRequested = 0;
        const socketStates = {};
        const apiStates = {};
        const promisesReauth = [];
        for (const socket of this.printerSocketAdaptersById.values()){
            try {
                if (socket.printerType === _printerapiinterface.OctoprintType && socket.needsReauth()) {
                    reauthRequested++;
                    const promise = socket.reauthSession().catch();
                    promisesReauth.push(promise);
                }
            } catch (e) {
                (0, _node.captureException)(e);
            }
        }
        await Promise.all(promisesReauth);
        const promisesOpenSocket = [];
        for (const socket of this.printerSocketAdaptersById.values()){
            try {
                if (socket.needsSetup() || socket.needsReopen()) {
                    socketSetupRequested++;
                    const promise = socket.setupSocketSession().then(()=>{
                        socket.open();
                    }).catch();
                    promisesOpenSocket.push(promise);
                }
            } catch (e) {
                (0, _node.captureException)(e);
            }
            const keySocket = socket.socketState;
            const valSocket = socketStates[keySocket];
            socketStates[keySocket] = valSocket ? valSocket + 1 : 1;
            const keyApi = socket.apiState;
            const valApi = apiStates[keyApi];
            apiStates[keyApi] = valApi ? valApi + 1 : 1;
        }
        await Promise.all(promisesOpenSocket);
    }
    createOrUpdateSocket(printer) {
        const { enabled, id } = printer;
        let foundAdapter = this.printerSocketAdaptersById.get(id);
        if (!enabled) {
            this.logger.log(`Printer is disabled. Deleting socket`);
            this.deleteSocket(id);
            return;
        }
        if (foundAdapter) {
            if (foundAdapter.printerType === printer.printerType) {
                foundAdapter.close();
                this.logger.log(`Closing printer socket for update`);
            } else {
                this.logger.log(`Printer type changed from ${foundAdapter.printerType} to ${printer.printerType}. Creating new socket adapter`);
                foundAdapter.close();
                foundAdapter = this.socketFactory.createInstance(printer.printerType);
                this.printerSocketAdaptersById.set(id, foundAdapter);
            }
        } else {
            foundAdapter = this.socketFactory.createInstance(printer.printerType);
            this.printerSocketAdaptersById.set(id, foundAdapter);
        }
        foundAdapter.registerCredentials({
            printerId: printer.id,
            loginDto: {
                apiKey: printer.apiKey,
                username: printer.username,
                password: printer.password,
                printerURL: printer.printerURL,
                printerType: printer.printerType
            }
        });
        foundAdapter.resetSocketState();
    }
    handleBatchPrinterCreated(event) {
        for (const printer of event.printers){
            this.handlePrinterCreated({
                printer
            });
        }
    }
    handlePrinterCreated(event) {
        this.createOrUpdateSocket(event.printer);
    }
    handlePrinterUpdated(event) {
        this.logger.log(`Printer updated. Updating socket`);
        this.createOrUpdateSocket(event.printer);
    }
    handlePrintersDeleted(event) {
        event.printerIds.forEach((id)=>{
            this.deleteSocket(id);
        });
    }
    subscribeToEvents() {
        this.eventEmitter2.on(_eventconstants.printerEvents.printerCreated, this.handlePrinterCreated.bind(this));
        this.eventEmitter2.on(_eventconstants.printerEvents.printersDeleted, this.handlePrintersDeleted.bind(this));
        this.eventEmitter2.on(_eventconstants.printerEvents.printerUpdated, this.handlePrinterUpdated.bind(this));
        this.eventEmitter2.on(_eventconstants.printerEvents.batchPrinterCreated, this.handleBatchPrinterCreated.bind(this));
    }
    deleteSocket(printerId) {
        const socket = this.printerSocketAdaptersById.get(printerId);
        socket?.disallowEmittingEvents();
        socket?.close();
        this.printerSocketAdaptersById.delete(printerId);
    }
}

//# sourceMappingURL=printer-socket.store.js.map