/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert } from "@fluidframework/common-utils";
import { isStableId } from "@fluidframework/container-runtime";
import { brand } from "../../util";
import { valueSymbol } from "../contextuallyTyped";
import { FieldKinds } from "../default-field-kinds";
import { getField } from "../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
 */
export 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);
}
export 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);
}
export function getOwnArrayKeys(length) {
    return Object.getOwnPropertyNames(Array.from(Array(length)));
}
export 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;
}
/**
 * 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.
 */
export 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[getField](nodeKeyFieldKey);
        assert(field.fieldSchema.kind.identifier === FieldKinds.nodeKey.identifier, 0x6df /* Invalid node key field kind */);
        const nodeKeyNode = field.getNode(0);
        const id = nodeKeyNode[valueSymbol];
        assert(typeof id === "string" && isStableId(id), 0x6e0 /* Malformed value encountered in node key field */);
        return brand(id);
    }
}
//# sourceMappingURL=utilities.js.map