"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.patchAstronautLabsMdns = patchAstronautLabsMdns;
const debug_1 = require("./debug");
const debug = (0, debug_1.createDebug)('signalk-server:mdns-patch');
const MEMBERSHIP_ERROR_PREFIX = 'Fatal error: Could not add membership to interface ';
let patchApplied = false;
let activeConsoleFilterCount = 0;
let restoreConsoleError;
function isErrnoException(error) {
    return error instanceof Error && 'code' in error;
}
function isIgnorableMembershipError(args) {
    const [message, error] = args;
    return (typeof message === 'string' &&
        message.startsWith(MEMBERSHIP_ERROR_PREFIX) &&
        isErrnoException(error) &&
        error.code === 'EADDRINUSE');
}
function installConsoleFilter() {
    activeConsoleFilterCount += 1;
    if (activeConsoleFilterCount > 1) {
        return;
    }
    const originalConsoleError = console.error;
    const wrappedConsoleError = (...args) => {
        if (isIgnorableMembershipError(args)) {
            const address = args[0].slice(MEMBERSHIP_ERROR_PREFIX.length);
            debug.enabled &&
                debug(`Ignoring @astronautlabs/mdns addMembership EADDRINUSE on ${address}`);
            return;
        }
        originalConsoleError(...args);
    };
    console.error = wrappedConsoleError;
    restoreConsoleError = () => {
        if (console.error === wrappedConsoleError) {
            console.error = originalConsoleError;
        }
        restoreConsoleError = undefined;
    };
}
function uninstallConsoleFilter() {
    if (activeConsoleFilterCount === 0) {
        return;
    }
    activeConsoleFilterCount -= 1;
    if (activeConsoleFilterCount === 0) {
        restoreConsoleError?.();
    }
}
function patchAstronautLabsMdns() {
    if (patchApplied) {
        return;
    }
    let networkInterfaceModule;
    try {
        // eslint-disable-next-line @typescript-eslint/no-require-imports
        networkInterfaceModule = require('@astronautlabs/mdns/dist/NetworkInterface');
    }
    catch (error) {
        debug.enabled &&
            debug(`Unable to patch @astronautlabs/mdns NetworkInterface: ${error}`);
        return;
    }
    const prototype = networkInterfaceModule.NetworkInterface?.prototype;
    const originalBindSocket = prototype?._bindSocket;
    if (typeof originalBindSocket !== 'function') {
        debug.enabled &&
            debug('Unable to patch @astronautlabs/mdns NetworkInterface._bindSocket');
        return;
    }
    if (originalBindSocket.__signalkPatched) {
        patchApplied = true;
        return;
    }
    const patchedBindSocket = function patchedBindSocket(...args) {
        installConsoleFilter();
        try {
            const result = originalBindSocket.apply(this, args);
            return result.finally(() => {
                uninstallConsoleFilter();
            });
        }
        catch (error) {
            uninstallConsoleFilter();
            throw error;
        }
    };
    patchedBindSocket.__signalkPatched = true;
    networkInterfaceModule.NetworkInterface.prototype._bindSocket =
        patchedBindSocket;
    patchApplied = true;
}
//# sourceMappingURL=mdnsPatch.js.map