"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSpec = getSpec;
exports.getGraphSpec = getGraphSpec;
exports.getSpecs = getSpecs;
exports.hasSpec = hasSpec;
exports.getComponentSpec = getComponentSpec;
exports.getSpecPins = getSpecPins;
exports.getSpecPinPlugs = getSpecPinPlugs;
exports.getSpecInputs = getSpecInputs;
exports.getSpecOutputs = getSpecOutputs;
exports.getSpecPinPlugCount = getSpecPinPlugCount;
exports.getSpecPinCount = getSpecPinCount;
exports.getSpecInputCount = getSpecInputCount;
exports.getSpecOutputCount = getSpecOutputCount;
exports.emptySpec = emptySpec;
exports.emptyShell = emptyShell;
exports.getSpecName = getSpecName;
exports.getSpecTitle = getSpecTitle;
exports.newSpecId = newSpecId;
exports.newUnitIdInSpecId = newUnitIdInSpecId;
exports.newUnitId = newUnitId;
exports.newUnitIdFromName = newUnitIdFromName;
exports.newMergeIdInSpec = newMergeIdInSpec;
exports.hasUnitId = hasUnitId;
exports.hasMergeId = hasMergeId;
exports.sameSpec = sameSpec;
exports.isInternalSpecId = isInternalSpecId;
exports.isSystemSpecId = isSystemSpecId;
exports.isSystemSpec = isSystemSpec;
exports.isEmptySpec = isEmptySpec;
exports.getSpecRenderById = getSpecRenderById;
exports.getSpecRender = getSpecRender;
exports.isComponentId = isComponentId;
exports.isComponentSpec = isComponentSpec;
exports.hasSubComponent = hasSubComponent;
exports.hasSubComponents = hasSubComponents;
exports.shouldRender = shouldRender;
exports.findInputDataExamples = findInputDataExamples;
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 clone_1 = require("../util/clone");
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;
}
function getGraphSpec(specs, id) {
    const spec = specs[id];
    return spec;
}
function getSpecs(specs) {
    return specs;
}
function hasSpec(specs, id) {
    const spec = specs[id];
    return !!spec;
}
function getComponentSpec(specs, id) {
    const spec = getSpec(specs, id);
    const { component = {} } = spec;
    return component;
}
function getSpecPins(specs, id, type) {
    const spec = getSpec(specs, id);
    const pins = spec[`${type}s`] || {};
    return pins;
}
function getSpecPinPlugs(specs, id, type, pinId) {
    return (0, object_1.deepGetOrDefault)(specs, [id, `${type}s`, pinId, 'plug'], {});
}
function getSpecInputs(specs, id) {
    const spec = getSpec(specs, id);
    const { inputs = {} } = spec;
    return inputs;
}
function getSpecOutputs(specs, id) {
    const spec = getSpec(specs, id);
    const { outputs = {} } = spec;
    return outputs;
}
function getSpecPinPlugCount(specs, id, type, pinId) {
    const plugs = getSpecPinPlugs(specs, id, type, pinId);
    const count = (0, f_2.keys)(plugs || {}).length;
    return count;
}
function getSpecPinCount(specs, id, type) {
    const pins = getSpecPins(specs, id, type);
    const inputCount = (0, f_2.keys)(pins || {}).length;
    return inputCount;
}
function getSpecInputCount(specs, id) {
    const inputs = getSpecInputs(specs, id);
    const inputCount = (0, f_2.keys)(inputs || {}).length;
    return inputCount;
}
function getSpecOutputCount(specs, id) {
    const outputs = getSpecOutputs(specs, id);
    const outputCount = (0, f_2.keys)(outputs || {}).length;
    return outputCount;
}
function emptySpec(init = {}) {
    const newSpec = (0, clone_1.clone)({
        ...(0, emptySpec_1.emptyGraphSpec)(),
        ...init,
    });
    return newSpec;
}
function emptyShell(from, init = {}) {
    const newSpec = (0, clone_1.clone)({
        ...(0, emptySpec_1.emptyGraphSpec)(),
        ...init,
    });
    return newSpec;
}
function getSpecName(specs, id) {
    const spec = specs[id];
    const { name } = spec;
    return name;
}
function getSpecTitle(specs, id) {
    return getSpecName(specs, id);
}
function newSpecId(specs) {
    const specId = (0, id_1.uuidNotIn)(specs);
    return specId;
}
function newUnitIdInSpecId(specs, id, unit_spec_id, blacklist) {
    const spec = getSpec(specs, id);
    return newUnitId(specs, spec, unit_spec_id, blacklist);
}
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);
}
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;
}
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;
}
function hasUnitId(spec, unit_id) {
    const { units = {} } = spec;
    const has = !!units[unit_id];
    return has;
}
function hasMergeId(spec, merge_id) {
    const { merges = {} } = spec;
    const has = !!merges[merge_id];
    return has;
}
function sameSpec(a_spec, b_spec) {
    // TODO
    return false;
}
function isInternalSpecId(specId) {
    return specId.startsWith('_');
}
function isSystemSpecId(specs, specId) {
    if (isInternalSpecId(specId)) {
        return true;
    }
    const spec = getSpec(specs, specId);
    const { system } = spec;
    return system;
}
function isSystemSpec(spec) {
    const { system } = spec;
    return system;
}
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;
}
function getSpecRenderById(specs, id) {
    const spec = getSpec(specs, id);
    return getSpecRender(spec);
}
function getSpecRender(spec) {
    const { render } = spec;
    return render;
}
function isComponentId(specs, id) {
    var _a;
    return ((_a = getSpecRenderById(specs, id)) !== null && _a !== void 0 ? _a : hasSubComponents(specs[id]));
}
function isComponentSpec(spec) {
    var _a;
    return (_a = getSpecRender(spec)) !== null && _a !== void 0 ? _a : hasSubComponents(spec);
}
function hasSubComponent(spec, subComponentId) {
    const { component = {} } = spec;
    const { subComponents = {} } = component;
    return !!subComponents[subComponentId];
}
function hasSubComponents(spec) {
    const { component = {} } = spec;
    const { subComponents = {} } = component;
    return (0, f_1.keyCount)(subComponents) > 0;
}
function shouldRender(componentSpec) {
    return !!componentSpec.children && componentSpec.children.length > 0;
}
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, kind = 'input', pinId, mergeId } = subPin;
                if (kind !== 'input') {
                    continue;
                }
                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 [];
}
//# sourceMappingURL=spec.js.map