"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.genericTreeDeleteIfEmpty = exports.genericTreeKeys = exports.setGenericTreeField = exports.getGenericTreeField = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
/**
 * Get a field from `node`, optionally modifying the tree to create it if missing.
 */
function getGenericTreeField(node, key, createIfMissing) {
    const children = getGenericTreeFieldMap(node, createIfMissing);
    // Do not just read field and check for undefined: see warning on FieldMapObject.
    if (Object.prototype.hasOwnProperty.call(children, key)) {
        return children[key] ?? (0, internal_1.fail)(0xaed /* This wont be undefined due to the check above */);
    }
    // Handle missing field:
    if (createIfMissing === false) {
        return [];
    }
    const newField = [];
    children[key] = newField;
    return newField;
}
exports.getGenericTreeField = getGenericTreeField;
/**
 * Get a FieldMap from `node`, optionally modifying the tree to create it if missing.
 */
function getGenericTreeFieldMap(node, createIfMissing) {
    let children = node.fields;
    if (children === undefined) {
        children = {};
        // Handle missing fields:
        if (createIfMissing) {
            node.fields = children;
        }
    }
    return children;
}
/**
 * Sets a field on `node`.
 */
function setGenericTreeField(node, key, content) {
    const children = getGenericTreeFieldMap(node, true);
    // like `children[keyString] = content;` except safe when keyString == "__proto__".
    Object.defineProperty(children, key, {
        enumerable: true,
        configurable: true,
        writable: true,
        value: content,
    });
}
exports.setGenericTreeField = setGenericTreeField;
/**
 * Returns keys for fields of `tree`.
 */
function genericTreeKeys(tree) {
    const fields = tree.fields;
    // This function is used when iterating through a tree.
    // This means that this is often called on nodes with no keys
    // (most trees are a large portion leaf nodes).
    // Therefore this function special cases empty fields objects as an optimization.
    if (fields === undefined) {
        return [];
    }
    return Object.keys(fields);
}
exports.genericTreeKeys = genericTreeKeys;
/**
 * Delete a field if empty.
 * Optionally delete FieldMapObject if empty as well.
 */
function genericTreeDeleteIfEmpty(node, key, removeMapObject) {
    const children = getGenericTreeFieldMap(node, false);
    if (Object.prototype.hasOwnProperty.call(children, key) && children[key]?.length === 0) {
        // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
        delete children[key];
        if (removeMapObject && Object.keys(children).length === 0) {
            delete node.fields;
        }
    }
}
exports.genericTreeDeleteIfEmpty = genericTreeDeleteIfEmpty;
//# sourceMappingURL=treeTextFormat.js.map