"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getServer = void 0;
/**
 * Reserves a server at given port range. Used by constructor of
 * {@link WebSocketProtocol}.
 *
 * @summary
 *
 * If first element of range is greater than last, port lookup will be done
 * downwards (e.g. `6472` → `6471`), else it will lookup ports upwards (e.g.
 * `6463` → `6464`).
 *
 * @param start - first element of port range
 * @param end - last element of port range
 * @param getter - method to get the server somehow
 *
 * @returns
 *
 * A {@link Promise} that resolves to object with the negotiated port number and the {@link Server} reference.
 */
async function getServer(start, end, getter, events, ...rest) {
    function isInteger(...args) {
        return args
            .map(number => typeof number === "number" && number === parseInt(number.toString()))
            .reduce((b1, b2) => b1 && b2);
    }
    function tryServer(port) {
        return new Promise(resolve => {
            if (start > end ? port < end : port > end)
                throw new Error("All ports from given range are busy!");
            const server = getter(port);
            server.once(events?.listening ?? "listening", () => {
                resolve({
                    server: server,
                    port
                });
                server.removeAllListeners(events?.error ?? "error");
            });
            server.once(events?.error ?? "error", () => {
                resolve(tryServer(start > end ? port - 1 : port + 1));
                server.close();
            });
        });
    }
    if (!isInteger(start, end))
        throw new TypeError("Invalid type of the arguments.");
    if (rest.length > 0)
        throw new TypeError("Too many function arguments.");
    return await tryServer(start);
}
exports.getServer = getServer;
//# sourceMappingURL=server.js.map