"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findInputDataExamples = exports.shouldRender = exports.hasSubComponents = exports.hasSubComponent = exports.isComponentSpec = exports.isComponentId = exports.getSpecRender = exports.getSpecRenderById = exports.injectSpecs = exports.__injectSpecs = exports.isEmptySpec = exports.isSystemSpec = exports.isSystemSpecId = exports.sameSpec = exports.hasMergeId = exports.hasUnitId = exports.newMergeIdInSpec = exports.newUnitIdFromName = exports.newUnitId = exports.newUnitIdInSpecId = exports.newSpecId = exports.getSpecTitle = exports.getSpecName = exports.emptyShell = exports.emptySpec = exports.getSpecOutputCount = exports.getSpecInputCount = exports.getSpecPinCount = exports.getSpecPinPlugCount = exports.getSpecOutputs = exports.getSpecInputs = exports.getSpecPinPlugs = exports.getSpecPins = exports.getComponentSpec = exports.hasSpec = exports.getSpecs = exports.getGraphSpec = exports.getSpec = void 0;
const STRING_1 = require("../constant/STRING");
const emptySpec_1 = require("../spec/emptySpec");
const f_1 = require("../system/core/object/KeyCount/f");
const f_2 = require("../system/f/object/Keys/f");
const id_1 = require("../util/id");
const object_1 = require("../util/object");
const string_1 = require("../util/string");
function getSpec(specs, id) {
    const spec = specs[id];
    return spec;
}
exports.getSpec = getSpec;
function getGraphSpec(specs, id) {
    const spec = specs[id];
    return spec;
}
exports.getGraphSpec = getGraphSpec;
function getSpecs(specs) {
    return specs;
}
exports.getSpecs = getSpecs;
function hasSpec(specs, id) {
    const spec = specs[id];
    return !!spec;
}
exports.hasSpec = hasSpec;
function getComponentSpec(specs, id) {
    const spec = getSpec(specs, id);
    const { component = {} } = spec;
    return component;
}
exports.getComponentSpec = getComponentSpec;
function getSpecPins(specs, id, type) {
    const spec = getSpec(specs, id);
    const pins = spec[`${type}s`] || {};
    return pins;
}
exports.getSpecPins = getSpecPins;
function getSpecPinPlugs(specs, id, type, pinId) {
    return (0, object_1.deepGetOrDefault)(specs, [id, `${type}s`, pinId, 'plug'], {});
}
exports.getSpecPinPlugs = getSpecPinPlugs;
function getSpecInputs(specs, id) {
    const spec = getSpec(specs, id);
    const { inputs = {} } = spec;
    return inputs;
}
exports.getSpecInputs = getSpecInputs;
function getSpecOutputs(specs, id) {
    const spec = getSpec(specs, id);
    const { outputs = {} } = spec;
    return outputs;
}
exports.getSpecOutputs = getSpecOutputs;
function getSpecPinPlugCount(specs, id, type, pinId) {
    const plugs = getSpecPinPlugs(specs, id, type, pinId);
    const count = (0, f_2.keys)(plugs || {}).length;
    return count;
}
exports.getSpecPinPlugCount = getSpecPinPlugCount;
function getSpecPinCount(specs, id, type) {
    const pins = getSpecPins(specs, id, type);
    const inputCount = (0, f_2.keys)(pins || {}).length;
    return inputCount;
}
exports.getSpecPinCount = getSpecPinCount;
function getSpecInputCount(specs, id) {
    const inputs = getSpecInputs(specs, id);
    const inputCount = (0, f_2.keys)(inputs || {}).length;
    return inputCount;
}
exports.getSpecInputCount = getSpecInputCount;
function getSpecOutputCount(specs, id) {
    const outputs = getSpecOutputs(specs, id);
    const outputCount = (0, f_2.keys)(outputs || {}).length;
    return outputCount;
}
exports.getSpecOutputCount = getSpecOutputCount;
function emptySpec(init = {}) {
    const newSpec = (0, object_1.clone)(Object.assign(Object.assign({}, (0, emptySpec_1.emptyGraphSpec)()), init));
    return newSpec;
}
exports.emptySpec = emptySpec;
function emptyShell(from, init = {}) {
    const newSpec = (0, object_1.clone)(Object.assign(Object.assign({}, (0, emptySpec_1.emptyGraphSpec)()), init));
    return newSpec;
}
exports.emptyShell = emptyShell;
function getSpecName(specs, id) {
    const spec = specs[id];
    const { name } = spec;
    return name;
}
exports.getSpecName = getSpecName;
function getSpecTitle(specs, id) {
    return getSpecName(specs, id);
}
exports.getSpecTitle = getSpecTitle;
function newSpecId(specs) {
    const specId = (0, id_1.uuidNotIn)(specs);
    return specId;
}
exports.newSpecId = newSpecId;
function newUnitIdInSpecId(specs, id, unit_spec_id, blacklist) {
    const spec = getSpec(specs, id);
    return newUnitId(specs, spec, unit_spec_id, blacklist);
}
exports.newUnitIdInSpecId = newUnitIdInSpecId;
function newUnitId(specs, spec, unit_spec_id, blacklist = new Set()) {
    const unit_spec = getSpec(specs, unit_spec_id);
    const { name = STRING_1.UNTITLED } = unit_spec;
    return newUnitIdFromName(spec, name, blacklist);
}
exports.newUnitId = newUnitId;
function newUnitIdFromName(spec, name, blacklist = new Set()) {
    const init_new_unit_id = (0, string_1.removeWhiteSpace)(name);
    let new_unit_id = init_new_unit_id;
    let i = 0;
    while (hasUnitId(spec, new_unit_id) || blacklist.has(new_unit_id)) {
        new_unit_id = init_new_unit_id + i;
        i++;
    }
    return new_unit_id;
}
exports.newUnitIdFromName = newUnitIdFromName;
function newMergeIdInSpec(spec, blacklist = new Set()) {
    let i = 0;
    let new_merge_id = `${i}`;
    while (hasMergeId(spec, new_merge_id) || blacklist.has(new_merge_id)) {
        i++;
        new_merge_id = `${i}`;
    }
    return new_merge_id;
}
exports.newMergeIdInSpec = newMergeIdInSpec;
function hasUnitId(spec, unit_id) {
    const { units = {} } = spec;
    const has = !!units[unit_id];
    return has;
}
exports.hasUnitId = hasUnitId;
function hasMergeId(spec, merge_id) {
    const { merges = {} } = spec;
    const has = !!merges[merge_id];
    return has;
}
exports.hasMergeId = hasMergeId;
function sameSpec(a_spec, b_spec) {
    // TODO
    return false;
}
exports.sameSpec = sameSpec;
function isSystemSpecId(specs, specId) {
    if (specId.startsWith('_')) {
        return true;
    }
    const spec = getSpec(specs, specId);
    const { system } = spec;
    return system;
}
exports.isSystemSpecId = isSystemSpecId;
function isSystemSpec(spec) {
    const { system } = spec;
    return system;
}
exports.isSystemSpec = isSystemSpec;
function isEmptySpec(spec) {
    const { units = {}, base } = spec;
    if (base) {
        return false;
    }
    const unitCount = (0, f_2.keys)(units).length;
    const empty = unitCount === 0;
    return empty;
}
exports.isEmptySpec = isEmptySpec;
function __injectSpecs(system, new_specs) {
    const map_spec_id = {};
    for (const spec_id in new_specs) {
        const spec = new_specs[spec_id];
        let new_spec_id = spec_id;
        let has_spec = false;
        while (system.hasSpec(new_spec_id)) {
            new_spec_id = system.newSpecId();
            has_spec = true;
        }
        if (has_spec) {
            map_spec_id[spec_id] = new_spec_id;
        }
        system.setSpec(spec_id, spec);
    }
    return map_spec_id;
}
exports.__injectSpecs = __injectSpecs;
function injectSpecs(specs, new_specs) {
    const map_spec_id = {};
    for (const spec_id in new_specs) {
        const spec = new_specs[spec_id];
        let new_spec_id = spec_id;
        let has_spec = false;
        while (specs[new_spec_id]) {
            new_spec_id = newSpecId(specs);
            has_spec = true;
        }
        if (has_spec) {
            map_spec_id[spec_id] = new_spec_id;
        }
        specs[spec_id] = spec;
    }
    return map_spec_id;
}
exports.injectSpecs = injectSpecs;
function getSpecRenderById(specs, id) {
    const spec = getSpec(specs, id);
    return getSpecRender(spec);
}
exports.getSpecRenderById = getSpecRenderById;
function getSpecRender(spec) {
    const { render } = spec;
    return render;
}
exports.getSpecRender = getSpecRender;
function isComponentId(specs, id) {
    var _a;
    return ((_a = getSpecRenderById(specs, id)) !== null && _a !== void 0 ? _a : hasSubComponents(specs[id]));
}
exports.isComponentId = isComponentId;
function isComponentSpec(spec) {
    var _a;
    return (_a = getSpecRender(spec)) !== null && _a !== void 0 ? _a : hasSubComponents(spec);
}
exports.isComponentSpec = isComponentSpec;
function hasSubComponent(spec, subComponentId) {
    const { component = {} } = spec;
    const { subComponents = {} } = component;
    return !!subComponents[subComponentId];
}
exports.hasSubComponent = hasSubComponent;
function hasSubComponents(spec) {
    const { component = {} } = spec;
    const { subComponents = {} } = component;
    return (0, f_1.keyCount)(subComponents) > 0;
}
exports.hasSubComponents = hasSubComponents;
function shouldRender(componentSpec) {
    return !!componentSpec.children && componentSpec.children.length > 0;
}
exports.shouldRender = shouldRender;
function findInputDataExamples(specs, spec_id, input_id) {
    const spec = getSpec(specs, spec_id);
    const { units, merges, inputs, base } = spec;
    const input = inputs[input_id];
    const { metadata = {} } = input;
    const { examples = [] } = metadata;
    if (examples.length > 0) {
        return examples;
    }
    else {
        if (base) {
            return [];
        }
        else {
            const { plug } = input;
            for (const subPinId in plug) {
                const subPin = plug[subPinId];
                const { unitId, pinId, mergeId } = subPin;
                if (unitId && pinId) {
                    const unit = units[unitId];
                    const unit_examples = findInputDataExamples(specs, unit.id, pinId);
                    if (unit_examples.length > 0) {
                        return unit_examples;
                    }
                }
                else if (mergeId) {
                    const merge = merges[mergeId];
                    for (const unitId in merge) {
                        const mergeUnit = merge[unitId];
                        const { input = {} } = mergeUnit;
                        const unit = units[unitId];
                        for (const inputId in input) {
                            const unit_examples = findInputDataExamples(specs, unit.id, inputId);
                            if (unit_examples.length > 0) {
                                return unit_examples;
                            }
                        }
                    }
                }
            }
        }
    }
    return [];
}
exports.findInputDataExamples = findInputDataExamples;
//# sourceMappingURL=spec.js.map