/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { fail } from "../../util/index.js";
/**
 * Get a field from `node`, optionally modifying the tree to create it if missing.
 */
export 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] ?? 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;
}
/**
 * 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`.
 */
export 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,
    });
}
/**
 * @returns keys for fields of `tree`.
 */
export 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);
}
/**
 * Delete a field if empty.
 * Optionally delete FieldMapObject if empty as well.
 */
export function genericTreeDeleteIfEmpty(node, key, removeMapObject) {
    const children = getGenericTreeFieldMap(node, false);
    if (Object.prototype.hasOwnProperty.call(children, key)) {
        if (children[key]?.length === 0) {
            // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
            delete children[key];
            if (removeMapObject) {
                if (Object.keys(children).length === 0) {
                    delete node.fields;
                }
            }
        }
    }
}
//# sourceMappingURL=treeTextFormat.js.map