"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bundleSpec = exports.unitBundleSpecById = exports.unitBundleSpec = void 0;
const spec_1 = require("./client/spec");
const evaluate_1 = require("./spec/evaluate");
const parser_1 = require("./spec/parser");
function unitBundleSpec(unit, specs) {
    const { id } = unit;
    const spec = (0, spec_1.getSpec)(specs, id);
    const { system } = spec;
    if (system) {
        return {
            unit: Object.assign({ id }, unit),
        };
    }
    else {
        const custom = {
            [id]: spec,
        };
        _bundle(spec, specs, custom, new Set());
        return {
            unit: Object.assign({ id }, unit),
            specs: custom,
        };
    }
}
exports.unitBundleSpec = unitBundleSpec;
function unitBundleSpecById(id, specs) {
    const spec = (0, spec_1.getSpec)(specs, id);
    const { base } = spec;
    if (base) {
        return {
            unit: {
                id,
            },
        };
    }
    else {
        const custom = {
            [id]: spec,
        };
        _bundle(spec, specs, custom, new Set());
        return {
            unit: {
                id,
            },
            specs: custom,
        };
    }
}
exports.unitBundleSpecById = unitBundleSpecById;
function bundleSpec(spec, specs) {
    const custom = {};
    const branch = new Set([]);
    _bundle(spec, specs, custom, branch);
    return { spec, specs: custom };
}
exports.bundleSpec = bundleSpec;
function _bundle(spec, specs, custom, branch) {
    if (!spec.id) {
        throw new Error('spec id is required');
    }
    if (spec.system) {
        return;
    }
    if (branch.has(spec.id)) {
        return;
    }
    branch.add(spec.id);
    _bundleUnits(spec, specs, custom, branch);
}
function _bundleUnits(spec, specs, custom, branch) {
    var _a;
    const { units = {} } = spec;
    for (const unit_id in units) {
        const unit = units[unit_id];
        const { id, input = {} } = unit;
        for (const inputId in input) {
            const _input = (_a = input[inputId]) !== null && _a !== void 0 ? _a : {};
            const { data } = _input;
            if (data) {
                const tree = (0, parser_1.getTree)(data);
                if (tree.type === parser_1.TreeNodeType.Unit) {
                    const bundle = (0, evaluate_1.evaluate)(tree.value, specs, {});
                    for (const specId in bundle.specs) {
                        const spec = bundle.specs[specId];
                        custom[specId] = spec;
                        _bundle(spec, specs, custom, branch);
                    }
                }
            }
        }
        const _spec = (0, spec_1.getSpec)(specs, id);
        if (!specs[id] || !(0, spec_1.isSystemSpecId)(specs, id)) {
            custom[id] = _spec;
        }
        _bundle(_spec, specs, custom, new Set(branch));
    }
}
//# sourceMappingURL=bundle.js.map