"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEmptyMerge = exports.getUnitInputDatum = exports.getUnitPinDatum = exports.getUnitMergesSpec = exports.makeFullSpecCollapseMap = exports.isPinSpecRef = exports.isSubPinSpecRef = exports.shouldExposePin = exports.findUnitAtPath = exports.findSpecAtPath = exports.findUnitPlugs = exports.findUnitPinPlug = exports.findMergePlugs = exports.findMergePlug = exports.hasPlug = exports.hasPinNamed = exports.hasMergePin = exports.hasMerge = exports.hasUnit = exports.forEachGraphSpecPinOfType = exports.forEachGraphSpecPinType = exports.forEachGraphSpecPinPlug = exports.forEachGraphSpecPin = exports.forEachSpecPin = exports.forEachOutputOnMerge = exports.forEachInputOnMerge = exports.forEachPinOnMerge = exports.forEachPinOnMerges = exports.getMergeUnitTypePinCount = exports.getMergeUnitPinCount = exports.getMergeTypePinCount = exports.getMergePinTypeCount = exports.getMergePinCount = exports.getPlugCount = exports.findPinMerge = exports.getSubPinSpec = exports.getPlugSpecs = exports.getPinSpec = exports.getUnitExposedPins = exports.getExposePinSpec = exports.getExposedPinSpecs = exports.findFirstMergePin = exports.opposite = exports.getMergePinNodeId = exports.getOutputNodeId = exports.getInputNodeId = exports.isPinRef = exports.isUnitPinConstant = exports.getPinNodeId = exports.isValidSpecName = void 0;
const spec_1 = require("../../client/spec");
const SELF_1 = require("../../constant/SELF");
const deepGet_1 = require("../../deepGet");
const f_1 = require("../../system/core/object/ForEachKeyValue/f");
const f_2 = require("../../system/core/object/KeyCount/f");
const f_3 = require("../../system/f/object/Keys/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 isUnitPinConstant(spec, unitId, type, pinId) {
    return (0, object_1.deepGetOrDefault)(spec, [unitId, type, pinId, 'constant'], false);
}
exports.isUnitPinConstant = isUnitPinConstant;
const isPinRef = ({ type, pinId }, spec) => {
    return ((0, object_1.deepGetOrDefault)(spec, [`${type}s`, pinId, 'ref'], false) ||
        (type === 'output' && pinId === SELF_1.SELF));
};
exports.isPinRef = isPinRef;
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 getMergePinNodeId(mergeId, type) {
    return `${mergeId}/${type}`;
}
exports.getMergePinNodeId = getMergePinNodeId;
function opposite(kind) {
    return kind === 'input' ? 'output' : 'input';
}
exports.opposite = opposite;
const findFirstMergePin = (merge, type) => {
    for (const unitId in merge) {
        if (merge[unitId][type]) {
            for (const pinId in merge[unitId][type]) {
                return {
                    unitId,
                    pinId,
                };
            }
        }
    }
};
exports.findFirstMergePin = findFirstMergePin;
const getExposedPinSpecs = (graph) => {
    return {
        input: graph.inputs,
        output: graph.outputs,
    };
};
exports.getExposedPinSpecs = getExposedPinSpecs;
const getExposePinSpec = (graph, type, pinId) => {
    return (0, object_1.deepGetOrDefault)(graph, [`${type}s`, pinId], undefined);
};
exports.getExposePinSpec = getExposePinSpec;
const getUnitExposedPins = (graph, unitId) => {
    const pins = {
        input: {},
        output: {},
    };
    (0, exports.forEachGraphSpecPin)(graph, (type, pinId, pinSpec) => {
        const { plug = {} } = pinSpec;
        for (const subPinId in plug) {
            const subPinSpec = plug[subPinId];
            const { unitId: unitId_, pinId: pinId_, mergeId } = subPinSpec;
            if (unitId_ === unitId) {
                (0, object_1.deepSet)(pins, [type, pinId_], {
                    type,
                    pinId,
                    subPinId,
                });
            }
            else if (mergeId) {
                //
            }
        }
    });
    return pins;
};
exports.getUnitExposedPins = getUnitExposedPins;
const getPinSpec = (graph, type, pinId) => {
    return (0, object_1.deepGetOrDefault)(graph, [`${type}s`, pinId], null);
};
exports.getPinSpec = getPinSpec;
const getPlugSpecs = (spec) => {
    const plugs = {
        input: {},
        output: {},
    };
    (0, exports.forEachGraphSpecPinPlug)(spec, (type, pinId, pinSpecs, subPinId, subPinSpec) => {
        const plug = (0, exports.getSubPinSpec)(spec, type, pinId, subPinId);
        (0, object_1.deepSet)(plugs, [type, pinId, subPinId], plug);
    });
    return plugs;
};
exports.getPlugSpecs = getPlugSpecs;
const getSubPinSpec = (graph, type, pinId, subPinId) => {
    return (0, object_1.deepGetOrDefault)(graph, [`${type}s`, pinId, 'plug', subPinId], null);
};
exports.getSubPinSpec = getSubPinSpec;
const findPinMerge = (spec, unitId, type, pinId) => {
    var _a, _b;
    const { merges = {} } = spec;
    for (const mergeId in merges) {
        const merge = merges[mergeId];
        if ((_b = (_a = merge === null || merge === void 0 ? void 0 : merge[unitId]) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b[pinId]) {
            return mergeId;
        }
    }
};
exports.findPinMerge = findPinMerge;
const getPlugCount = (spec, type, pinId) => {
    return (0, f_2.keyCount)((0, object_1.deepGetOrDefault)(spec, [`${type}s`, pinId, 'plug'], {}));
};
exports.getPlugCount = getPlugCount;
const getMergePinCount = (merge) => {
    return (0, object_1.reduceObj)(merge, (count, mergeUnit) => {
        return count + (0, exports.getMergeUnitPinCount)(mergeUnit);
    }, 0);
};
exports.getMergePinCount = getMergePinCount;
const getMergePinTypeCount = (merge, type) => {
    return (0, object_1.reduceObj)(merge, (count, mergeUnit) => {
        return count + (0, exports.getMergeUnitTypePinCount)(mergeUnit, type);
    }, 0);
};
exports.getMergePinTypeCount = getMergePinTypeCount;
const getMergeTypePinCount = (merge, type) => {
    return (0, object_1.reduceObj)(merge, (count, mergeUnit) => {
        return count + (0, exports.getMergeUnitTypePinCount)(mergeUnit, type);
    }, 0);
};
exports.getMergeTypePinCount = getMergeTypePinCount;
const getMergeUnitPinCount = (mergeUnit) => {
    return ((0, exports.getMergeUnitTypePinCount)(mergeUnit, 'input') +
        (0, exports.getMergeUnitTypePinCount)(mergeUnit, 'output'));
};
exports.getMergeUnitPinCount = getMergeUnitPinCount;
const getMergeUnitTypePinCount = (mergeUnit, type) => {
    const { [type]: pins = {} } = mergeUnit;
    const pinCount = (0, object_1._keyCount)(pins);
    return pinCount;
};
exports.getMergeUnitTypePinCount = getMergeUnitTypePinCount;
const forEachPinOnMerges = (merges, callback) => {
    (0, f_1.default)(merges || {}, (merge, mergeId) => {
        (0, exports.forEachPinOnMerge)(merge, (unitId, type, pinId, data) => callback(mergeId, unitId, type, pinId, data));
    });
};
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 forEachInputOnMerge = (merge, callback) => {
    (0, f_1.default)(merge, ({ input }, unitId) => {
        (0, f_1.default)(input || {}, (_, inputId) => {
            callback(unitId, 'input', inputId, _);
        });
    });
};
exports.forEachInputOnMerge = forEachInputOnMerge;
const forEachOutputOnMerge = (merge, callback) => {
    (0, f_1.default)(merge, ({ output }, unitId) => {
        (0, f_1.default)(output || {}, (_, outputId) => {
            callback(unitId, 'output', outputId, _);
        });
    });
};
exports.forEachOutputOnMerge = forEachOutputOnMerge;
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 forEachGraphSpecPinPlug = (spec, callback) => {
    (0, exports.forEachGraphSpecPin)(spec, (type, pinId, pinSpec) => {
        var _a;
        for (const subPinId in (_a = pinSpec.plug) !== null && _a !== void 0 ? _a : {}) {
            const subPinSpec = pinSpec.plug[subPinId];
            callback(type, pinId, pinSpec, subPinId, subPinSpec);
        }
    });
};
exports.forEachGraphSpecPinPlug = forEachGraphSpecPinPlug;
const forEachGraphSpecPinType = (spec, type, callback) => {
    (0, exports.forEachGraphSpecPinOfType)(spec, type, (pinId, pinSpec) => {
        callback(type, pinId, pinSpec);
    });
};
exports.forEachGraphSpecPinType = forEachGraphSpecPinType;
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 hasUnit = (spec, unitId) => {
    var _a;
    return !!((_a = spec.units) === null || _a === void 0 ? void 0 : _a[unitId]);
};
exports.hasUnit = hasUnit;
const hasMerge = (spec, mergeId) => {
    var _a;
    return !!((_a = spec.merges) === null || _a === void 0 ? void 0 : _a[mergeId]);
};
exports.hasMerge = hasMerge;
const hasMergePin = (spec, mergeId, unitId, type, pinId) => {
    return !!(0, object_1.deepGetOrDefault)(spec, ['merges', mergeId, unitId, type, pinId], false);
};
exports.hasMergePin = hasMergePin;
const hasPinNamed = (spec, type, pinId) => {
    return !!(0, object_1.deepGetOrDefault)(spec, [`${type}s`, pinId], false);
};
exports.hasPinNamed = hasPinNamed;
const hasPlug = (spec, type, pinId, subPinId) => {
    return !!(0, object_1.deepGetOrDefault)(spec, [`${type}s`, pinId, 'plug', subPinId], false);
};
exports.hasPlug = hasPlug;
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 findMergePlugs = (spec, mergeId) => {
    const mergePlugs = {
        input: null,
        output: null,
    };
    (0, exports.forEachGraphSpecPin)(spec, (type, pinId, pinSpec) => {
        const { plug = {} } = pinSpec;
        for (const subPinId in plug) {
            const subPin = plug[subPinId];
            if (subPin.mergeId === mergeId) {
                mergePlugs[type] = {
                    pinId,
                    type,
                    subPinId,
                };
            }
        }
    });
    return mergePlugs;
};
exports.findMergePlugs = findMergePlugs;
const findUnitPinPlug = (spec, unitId, type, pinId) => {
    let pinPlug = null;
    (0, exports.forEachGraphSpecPinOfType)(spec, type, (_pinId, pinSpec) => {
        const { plug = {} } = pinSpec;
        for (const subPinId in plug) {
            const subPin = plug[subPinId];
            if (subPin.unitId === unitId && subPin.pinId === pinId) {
                pinPlug = {
                    pinId: _pinId,
                    type,
                    subPinId,
                };
            }
        }
    });
    return pinPlug;
};
exports.findUnitPinPlug = findUnitPinPlug;
function findUnitPlugs(spec, unitId) {
    const plugs = {
        input: {},
        output: {},
    };
    (0, exports.forEachGraphSpecPinPlug)(spec, (type, pinId, pinSpec, subPinId, subPinSpec) => {
        var _a;
        if (subPinSpec.unitId === unitId) {
            (0, object_1.deepSet)(plugs, [(_a = subPinSpec.kind) !== null && _a !== void 0 ? _a : type, subPinSpec.pinId], {
                type,
                pinId,
                subPinId,
            });
        }
    });
    return plugs;
}
exports.findUnitPlugs = findUnitPlugs;
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;
const findUnitAtPath = (specs, spec, path, unit) => {
    if (path.length === 0) {
        return unit;
    }
    else {
        const [unitId, ...rest] = path;
        const unit = spec.units[unitId];
        const unitSpec = (0, spec_1.getSpec)(specs, unit.id);
        return (0, exports.findUnitAtPath)(specs, unitSpec, rest, unit);
    }
};
exports.findUnitAtPath = findUnitAtPath;
const shouldExposePin = (type, pinId, pinSpec, subPinId, subPinSpec, merged, outerPlug = null) => {
    var _a;
    if (merged || outerPlug) {
        return false;
    }
    if ((0, f_2.keyCount)((_a = pinSpec.plug) !== null && _a !== void 0 ? _a : {}) > 1) {
        return true;
    }
    if (subPinSpec.pinId === pinId) {
        return false;
    }
    return true;
};
exports.shouldExposePin = shouldExposePin;
function isSubPinSpecRef(specs, spec, type, subPinSpec) {
    let ref = false;
    if (subPinSpec.unitId && subPinSpec.pinId) {
        const unit = spec.units[subPinSpec.unitId];
        const unit_spec = (0, spec_1.getSpec)(specs, unit.id);
        ref = (0, exports.isPinRef)({ type, pinId: subPinSpec.pinId }, unit_spec);
    }
    else if (subPinSpec.mergeId) {
        const merge = spec.merges[subPinSpec.mergeId];
        (0, exports.forEachPinOnMerge)(merge, (unitId, type, pinId) => {
            const unit = spec.units[unitId];
            const unit_spec = (0, spec_1.getSpec)(specs, unit.id);
            if (ref === true) {
                return;
            }
            ref = (0, exports.isPinRef)({ type, pinId: subPinSpec.pinId }, unit_spec);
        });
    }
    return ref;
}
exports.isSubPinSpecRef = isSubPinSpecRef;
function isPinSpecRef(specs, spec, type, pinSpec) {
    const { plug = {} } = pinSpec;
    for (const subPinId in plug) {
        const subPinSpec = plug[subPinId];
        if (isSubPinSpecRef(specs, spec, type, subPinSpec)) {
            return true;
        }
    }
    return false;
}
exports.isPinSpecRef = isPinSpecRef;
function makeFullSpecCollapseMap(unitId, spec, unitIdMap, mergeIdMap, plugIdMap, { getUnitMerges, getUnitPlugs, getMerge, getPinMergeId, }) {
    var _a, _b;
    const { units = {}, merges = {}, inputs = {}, outputs = {} } = spec;
    const nodeIds = {
        unit: (0, f_3.keys)(units),
        merge: (0, f_3.keys)(merges),
        link: [],
        plug: [],
    };
    const unitMerges = getUnitMerges(unitId);
    const unitPlugs = getUnitPlugs(unitId);
    const nextIdMap = {
        unit: unitIdMap,
        merge: mergeIdMap,
        plug: (0, object_1.mapObjVK)(plugIdMap, (pinMap) => (0, object_1.mapObjVK)(pinMap, (subPinMap) => (0, object_1.mapObjVK)(subPinMap, (nextSubPinId) => ({
            subPinId: nextSubPinId,
        })))),
    };
    const nextPinIdMap = {};
    const nextMergePinId = {};
    const nextPlugSpec = {};
    const nextUnitPinMergeMap = {};
    (0, exports.forEachPinOnMerges)(merges, (mergeId, mergeUnitId, mergeUnitType, mergePinId) => {
        var _a;
        const nextMergeId = (_a = mergeIdMap[mergeId]) !== null && _a !== void 0 ? _a : mergeId;
        (0, object_1.deepSet)(nextUnitPinMergeMap, [mergeUnitId, mergeUnitType, mergePinId], nextMergeId);
    });
    const processPins = (type, pins) => {
        for (const pinId in pins) {
            const pin = pins[pinId];
            processPin(type, pinId, pin);
        }
    };
    const processPin = (type, pinId, pin) => {
        var _a, _b;
        const { plug, ref, defaultIgnored } = pin;
        const mergeId = getPinMergeId(unitId, type, pinId);
        const merged = !!mergeId;
        const outerPlug = (0, object_1.deepGetOrDefault)(unitPlugs, [type, pinId], null);
        for (const subPinId in plug) {
            const subPinSpec = plug[subPinId];
            if ((0, exports.shouldExposePin)(type, pinId, pin, subPinId, subPinSpec, merged, outerPlug)) {
                nodeIds.plug.push({ type, pinId, subPinId });
                let nextSubPinSpec = {};
                if (subPinSpec.unitId && subPinSpec.pinId) {
                    const nextUnitId = (_a = nextIdMap.unit[subPinSpec.unitId]) !== null && _a !== void 0 ? _a : subPinSpec.unitId;
                    nextSubPinSpec = {
                        unitId: nextUnitId,
                        pinId: subPinSpec.pinId,
                    };
                }
                else {
                    const nextMergeId = (_b = nextIdMap.merge[subPinSpec.mergeId]) !== null && _b !== void 0 ? _b : subPinSpec.mergeId;
                    nextSubPinSpec = {
                        mergeId: nextMergeId,
                    };
                }
                (0, object_1.deepSet)(nextPlugSpec, [type, pinId, subPinId], nextSubPinSpec);
            }
            if (subPinSpec.unitId && subPinSpec.pinId) {
                (0, exports.forEachPinOnMerges)(unitMerges, (mergeId, mergeUnitId, mergeUnitType, mergeUnitPinId) => {
                    var _a;
                    const merge = getMerge(mergeId);
                    const merge_clone = (0, object_1.clone)(merge);
                    delete merge_clone[unitId];
                    const nextUnitId = (_a = nextIdMap.unit[subPinSpec.unitId]) !== null && _a !== void 0 ? _a : subPinSpec.unitId;
                    merge_clone[nextUnitId] = {
                        [mergeUnitType]: { [subPinSpec.pinId]: true },
                    };
                    if (mergeUnitId === unitId &&
                        mergeUnitType === type &&
                        mergeUnitPinId === pinId) {
                        (0, object_1.deepSet)(nextPinIdMap, [subPinSpec.unitId, mergeUnitType, subPinSpec.pinId], {
                            pinId,
                            subPinId,
                            ref,
                            defaultIgnored,
                            mergeId,
                            merge: merge_clone,
                        });
                    }
                });
            }
            else if (subPinSpec.mergeId) {
                const mergeSpec = merges[subPinSpec.mergeId];
                if (isEmptyMerge(mergeSpec)) {
                    const mergeId = getPinMergeId(unitId, type, pinId);
                    if (mergeId) {
                        const merge = getMerge(mergeId);
                        const oppositeMerge = (0, object_1.clone)(merge);
                        delete oppositeMerge[unitId];
                        (0, object_1.deepSet)(nextMergePinId, [subPinSpec.mergeId, type], {
                            mergeId,
                            pinId,
                            subPinSpec: {
                                mergeId: subPinSpec.mergeId,
                            },
                            oppositeMerge,
                        });
                    }
                    else {
                        (0, object_1.deepSet)(nextMergePinId, [subPinSpec.mergeId, type], {
                            mergeId: null,
                            pinId: null,
                            subPinSpec: {},
                            oppositeMerge: {},
                        });
                    }
                }
                else {
                    const mergeId = getPinMergeId(unitId, type, pinId);
                    if (mergeId) {
                        const merge = getMerge(mergeId);
                        const oppositeMerge = (0, object_1.clone)(merge);
                        delete oppositeMerge[unitId];
                        (0, object_1.deepSet)(nextMergePinId, [subPinSpec.mergeId, type], {
                            mergeId,
                            oppositeMerge,
                        });
                    }
                }
            }
        }
    };
    processPins('input', inputs);
    processPins('output', outputs);
    for (const mergeId in unitMerges) {
        const merge = getMerge(mergeId);
        const merge_clone = (0, object_1.clone)(merge);
        const merge_unit = merge_clone[unitId];
        if ((0, object_1.isEmptyObject)((_a = merge_unit['input']) !== null && _a !== void 0 ? _a : {})) {
            delete merge_unit['input'];
        }
        if ((0, object_1.isEmptyObject)((_b = merge_unit['output']) !== null && _b !== void 0 ? _b : {})) {
            delete merge_unit['output'];
        }
        const merge_unit_pin_type = (0, object_1.getObjSingleKey)(merge_unit);
        const merge_unit_pin_id = (0, object_1.getObjSingleKey)(merge_unit[merge_unit_pin_type]);
        delete merge_clone[unitId];
        const merge_pin_count = (0, exports.getMergePinCount)(merge_clone);
        if (merge_pin_count === 1 && merge_unit_pin_id !== SELF_1.SELF) {
            const mergeUnitPinSpec = (0, deepGet_1.default)(spec, [
                `${merge_unit_pin_type}s`,
                merge_unit_pin_id,
            ]);
            const { plug = {} } = mergeUnitPinSpec;
            let is_empty_merge = false;
            for (const subPinId in plug) {
                const subPinSpec = plug[subPinId];
                if (subPinSpec.mergeId) {
                    const mergeSpec = merges[subPinSpec.mergeId];
                    const mergePinCount = (0, exports.getMergePinCount)(mergeSpec);
                    if (mergePinCount === 0) {
                        is_empty_merge = true;
                    }
                }
            }
            if (!is_empty_merge) {
                const otherUnitId = (0, object_1.getObjSingleKey)(merge_clone);
                const otherUnitPinType = (0, object_1.getObjSingleKey)(merge_clone[otherUnitId]);
                const otherUnitPinId = (0, object_1.getObjSingleKey)(merge_clone[otherUnitId][otherUnitPinType]);
                (0, object_1.deepSet)(nextIdMap, ['link', otherUnitId, otherUnitPinType, otherUnitPinId], {
                    mergeId,
                    oppositePinId: merge_unit_pin_id,
                });
            }
        }
        else {
            // TODO
        }
    }
    (0, exports.forEachPinOnMerges)(unitMerges, (mergeId, mergeUnitId, mergeUnitType, mergeUnitPinId) => {
        const merge = getMerge(mergeId);
    });
    const collapseMap = {
        nodeIds,
        nextSpecId: null,
        nextIdMap,
        nextPinIdMap,
        nextMergePinId,
        nextPlugSpec,
        nextUnitPinMergeMap,
        nextSubComponentParentMap: {},
        nextSubComponentChildrenMap: {},
        nextSubComponentIndexMap: {},
    };
    return collapseMap;
}
exports.makeFullSpecCollapseMap = makeFullSpecCollapseMap;
function getUnitMergesSpec(spec, unitId) {
    const { merges } = spec;
    const unit_merges = {};
    for (const mergeId in merges) {
        const merge = merges[mergeId];
        if (merge[unitId]) {
            unit_merges[mergeId] = merge;
        }
    }
    return unit_merges;
}
exports.getUnitMergesSpec = getUnitMergesSpec;
function getUnitPinDatum(spec, unitId, type, pinId) {
    return (0, object_1.deepGetOrDefault)(spec, ['units', unitId, type, pinId, 'data'], undefined);
}
exports.getUnitPinDatum = getUnitPinDatum;
function getUnitInputDatum(spec, unitId, pinId) {
    return getUnitPinDatum(spec, unitId, 'input', pinId);
}
exports.getUnitInputDatum = getUnitInputDatum;
function isEmptyMerge(mergeSpec) {
    return (0, exports.getMergePinCount)(mergeSpec) === 0;
}
exports.isEmptyMerge = isEmptyMerge;
//# sourceMappingURL=spec.js.map