"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.single = exports.mapOutputUpdates = exports.mapOutputValues = exports.mapInput = exports.readChannels = exports.readChannel = void 0;
const constants_js_1 = require("../constants.cjs");
const errors_js_1 = require("../errors.cjs");
function readChannel(channels, chan, catch_ = true, returnException = false) {
    try {
        return channels[chan].get();
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
    }
    catch (e) {
        if (e.name === errors_js_1.EmptyChannelError.name) {
            if (returnException) {
                return e;
            }
            else if (catch_) {
                return null;
            }
        }
        throw e;
    }
}
exports.readChannel = readChannel;
function readChannels(channels, select, skipEmpty = true
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) {
    if (Array.isArray(select)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const values = {};
        for (const k of select) {
            try {
                values[k] = readChannel(channels, k, !skipEmpty);
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
            }
            catch (e) {
                if (e.name === errors_js_1.EmptyChannelError.name) {
                    continue;
                }
            }
        }
        return values;
    }
    else {
        return readChannel(channels, select);
    }
}
exports.readChannels = readChannels;
/**
 * Map input chunk to a sequence of pending writes in the form [channel, value].
 */
function* mapInput(inputChannels, 
// eslint-disable-next-line @typescript-eslint/no-explicit-any
chunk
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) {
    if (chunk !== undefined && chunk !== null) {
        if (Array.isArray(inputChannels) &&
            typeof chunk === "object" &&
            !Array.isArray(chunk)) {
            for (const k in chunk) {
                if (inputChannels.includes(k)) {
                    yield [k, chunk[k]];
                }
            }
        }
        else if (Array.isArray(inputChannels)) {
            throw new Error("Input chunk must be an object when inputChannels is an array");
        }
        else {
            yield [inputChannels, chunk];
        }
    }
}
exports.mapInput = mapInput;
/**
 * Map pending writes (a sequence of tuples (channel, value)) to output chunk.
 */
function* mapOutputValues(outputChannels, pendingWrites, channels
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) {
    if (Array.isArray(outputChannels)) {
        if (pendingWrites.find(([chan, _]) => outputChannels.includes(chan))) {
            yield readChannels(channels, outputChannels);
        }
    }
    else {
        if (pendingWrites.some(([chan, _]) => chan === outputChannels)) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            yield readChannel(channels, outputChannels);
        }
    }
}
exports.mapOutputValues = mapOutputValues;
/**
 * Map pending writes (a sequence of tuples (channel, value)) to output chunk.
 */
function* mapOutputUpdates(outputChannels, tasks
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) {
    const outputTasks = tasks.filter((task) => task.config === undefined || !task.config.tags?.includes(constants_js_1.TAG_HIDDEN));
    if (Array.isArray(outputChannels)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const updated = {};
        for (const task of outputTasks) {
            if (task.writes.some(([chan, _]) => outputChannels.includes(chan))) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                const nodes = {};
                for (const [chan, value] of task.writes) {
                    if (outputChannels.includes(chan)) {
                        nodes[chan] = value;
                    }
                }
                updated[task.name] = nodes;
            }
        }
        if (Object.keys(updated).length > 0) {
            yield updated;
        }
    }
    else {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const updated = {};
        for (const task of outputTasks) {
            for (const [chan, value] of task.writes) {
                if (chan === outputChannels) {
                    updated[task.name] = value;
                }
            }
        }
        if (Object.keys(updated).length > 0) {
            yield updated;
        }
    }
}
exports.mapOutputUpdates = mapOutputUpdates;
function single(iter) {
    // eslint-disable-next-line no-unreachable-loop
    for (const value of iter) {
        return value;
    }
    return null;
}
exports.single = single;
