"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findSpecAtPath = exports.findMergePlug = exports.specHasMerge = exports.specHasUnit = exports.forEachGraphSpecPinOfType = exports.forEachGraphSpecPin = exports.forEachSpecPin = exports.forEachPinOnMerge = exports.forEachPinOnMerges = exports.getMergeUnitPinCount = exports.getMergePinCount = exports.findMergePin = exports.opposite = exports.getMergePinNodeId = exports.getExposedPinId = exports.getOutputNodeId = exports.getInputNodeId = exports.getPinNodeId = exports.isValidSpecName = void 0;
const spec_1 = require("../client/spec");
const f_1 = require("../system/core/object/ForEachKeyValue/f");
const object_1 = require("../util/object");
function isValidSpecName(name) {
    return !!/^[A-Za-z_ ][A-Za-z\d_ ]*$/g.exec(name);
}
exports.isValidSpecName = isValidSpecName;
function getPinNodeId(unitId, type, pinId) {
    return `${unitId}/${type}/${pinId}`;
}
exports.getPinNodeId = getPinNodeId;
function getInputNodeId(unitId, pinId) {
    return getPinNodeId(unitId, 'input', pinId);
}
exports.getInputNodeId = getInputNodeId;
function getOutputNodeId(unitId, pinId) {
    return getPinNodeId(unitId, 'output', pinId);
}
exports.getOutputNodeId = getOutputNodeId;
function getExposedPinId(id, type) {
    return `${type}/${id}`;
}
exports.getExposedPinId = getExposedPinId;
function getMergePinNodeId(mergeId, type) {
    return `${mergeId}/${type}`;
}
exports.getMergePinNodeId = getMergePinNodeId;
function opposite(kind) {
    return kind === 'input' ? 'output' : 'input';
}
exports.opposite = opposite;
const findMergePin = (merge, type) => {
    for (const unitId in merge) {
        if (merge[unitId][type]) {
            for (const pinId in merge[unitId][type]) {
                return {
                    unitId,
                    pinId,
                };
            }
        }
    }
};
exports.findMergePin = findMergePin;
const getMergePinCount = (merge) => {
    return (0, object_1.reduceObj)(merge, (count, mergeUnit) => {
        return count + (0, exports.getMergeUnitPinCount)(mergeUnit);
    }, 0);
};
exports.getMergePinCount = getMergePinCount;
const getMergeUnitPinCount = (merge_unit) => {
    const { input = {}, output = {} } = merge_unit;
    const input_count = (0, object_1._keyCount)(input);
    const output_count = (0, object_1._keyCount)(output);
    const count = input_count + output_count;
    return count;
};
exports.getMergeUnitPinCount = getMergeUnitPinCount;
const forEachPinOnMerges = (merges, callback) => {
    (0, f_1.default)(merges || {}, (merge, mergeId) => {
        (0, exports.forEachPinOnMerge)(merge, (unitId, type, pinId) => callback(mergeId, unitId, type, pinId));
    });
};
exports.forEachPinOnMerges = forEachPinOnMerges;
const forEachPinOnMerge = (merge, callback) => {
    (0, f_1.default)(merge, ({ input, output }, unitId) => {
        (0, f_1.default)(input || {}, (_, inputId) => {
            callback(unitId, 'input', inputId);
        });
        (0, f_1.default)(output || {}, (_, outputId) => {
            callback(unitId, 'output', outputId);
        });
    });
};
exports.forEachPinOnMerge = forEachPinOnMerge;
const forEachSpecPin = (spec, callback) => {
    const { inputs = {}, outputs = {} } = spec;
    (0, f_1.default)(inputs, (inputSpec, inputId) => {
        callback('input', inputId, inputSpec);
    });
    (0, f_1.default)(outputs, (outputSpec, outputId) => {
        callback('output', outputId, outputSpec);
    });
};
exports.forEachSpecPin = forEachSpecPin;
const forEachGraphSpecPin = (spec, callback) => {
    (0, exports.forEachGraphSpecPinOfType)(spec, 'input', (inputId, inputSpec) => {
        callback('input', inputId, inputSpec);
    });
    (0, exports.forEachGraphSpecPinOfType)(spec, 'output', (outputSpec, outputId) => {
        callback('output', outputSpec, outputId);
    });
};
exports.forEachGraphSpecPin = forEachGraphSpecPin;
const forEachGraphSpecPinOfType = (spec, type, callback) => {
    var _a;
    (0, f_1.default)((_a = spec[`${type}s`]) !== null && _a !== void 0 ? _a : {}, (pinSpec, pinId) => {
        callback(pinId, pinSpec);
    });
};
exports.forEachGraphSpecPinOfType = forEachGraphSpecPinOfType;
const specHasUnit = (spec, unitId) => {
    var _a;
    return !!((_a = spec.units) === null || _a === void 0 ? void 0 : _a[unitId]);
};
exports.specHasUnit = specHasUnit;
const specHasMerge = (spec, mergeId) => {
    var _a;
    return !!((_a = spec.merges) === null || _a === void 0 ? void 0 : _a[mergeId]);
};
exports.specHasMerge = specHasMerge;
const findMergePlug = (spec, type, mergeId) => {
    let mergePlug = null;
    (0, exports.forEachGraphSpecPinOfType)(spec, type, (pinId, pinSpec) => {
        const { plug = {} } = pinSpec;
        for (const subPinId in plug) {
            const subPin = plug[subPinId];
            if (subPin.mergeId === mergeId) {
                mergePlug = {
                    pinId,
                    type,
                    subPinId,
                };
            }
        }
    });
    return mergePlug;
};
exports.findMergePlug = findMergePlug;
const findSpecAtPath = (specs, spec, path) => {
    if (path.length === 0) {
        return spec;
    }
    else {
        const [unitId, ...rest] = path;
        const unit = spec.units[unitId];
        const unitSpec = (0, spec_1.getSpec)(specs, unit.id);
        return (0, exports.findSpecAtPath)(specs, unitSpec, rest);
    }
};
exports.findSpecAtPath = findSpecAtPath;
//# sourceMappingURL=util.js.map