"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStableNodeKey = exports.keyIsValidIndex = exports.getOwnArrayKeys = exports.adaptWithProxy = exports.isPrimitive = void 0;
const common_utils_1 = require("@fluidframework/common-utils");
const container_runtime_1 = require("@fluidframework/container-runtime");
const util_1 = require("../../util");
const contextuallyTyped_1 = require("../contextuallyTyped");
const default_field_kinds_1 = require("../default-field-kinds");
const untypedTree_1 = require("../untypedTree");
/**
 * @returns true iff `schema` trees should default to being viewed as just their value when possible.
 *
 * @remarks
 * This may return true for some types which EditableTree does not unwrap to just their value,
 * since EditableTree avoids ever unwrapping primitives that are objects
 * so users checking for primitives by type won't be broken.
 * Checking for this object case is done elsewhere.
 * @alpha
 */
function isPrimitive(schema) {
    // TODO: use a separate `ITreeSchema` type, with metadata that determines if the type is primitive.
    // Since the above is not done yet, use use a heuristic:
    return (schema.leafValue !== undefined &&
        schema.structFields.size === 0 &&
        schema.mapFields === undefined);
}
exports.isPrimitive = isPrimitive;
function adaptWithProxy(target, proxyHandler) {
    // Proxy constructor assumes handler emulates target's interface.
    // Ours does not, so this cast is required.
    return new Proxy(target, proxyHandler);
}
exports.adaptWithProxy = adaptWithProxy;
function getOwnArrayKeys(length) {
    return Object.getOwnPropertyNames(Array.from(Array(length)));
}
exports.getOwnArrayKeys = getOwnArrayKeys;
function keyIsValidIndex(key, length) {
    const index = Number(key);
    if (typeof key === "string" && String(index) !== key)
        return false;
    return Number.isInteger(index) && 0 <= index && index < length;
}
exports.keyIsValidIndex = keyIsValidIndex;
/**
 * Retrieve a {@link StableNodeKey} on the given {@link EditableTree} node.
 * @param nodeKeyFieldKey - the key of the field under which the node key resides
 * @param node - the {@link EditableTree} node from which to retrieve the node key
 * @returns the {@link StableNodeKey} on `node`, or undefined if there is none.
 */
function getStableNodeKey(nodeKeyFieldKey, node) {
    if (nodeKeyFieldKey in node) {
        // Get the ID via a wrapped node rather than an unwrapped node (`node[nodeKeyFieldKeySymbol]`)
        // so that the field kind can be checked
        const field = node[untypedTree_1.getField](nodeKeyFieldKey);
        (0, common_utils_1.assert)(field.fieldSchema.kind.identifier === default_field_kinds_1.FieldKinds.nodeKey.identifier, 0x6df /* Invalid node key field kind */);
        const nodeKeyNode = field.getNode(0);
        const id = nodeKeyNode[contextuallyTyped_1.valueSymbol];
        (0, common_utils_1.assert)(typeof id === "string" && (0, container_runtime_1.isStableId)(id), 0x6e0 /* Malformed value encountered in node key field */);
        return (0, util_1.brand)(id);
    }
}
exports.getStableNodeKey = getStableNodeKey;
//# sourceMappingURL=utilities.js.map