"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _TreeNodeKernel_hydrated, _TreeNodeKernel_events;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TreeNodeKernel = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const index_js_1 = require("../events/index.js");
const index_js_2 = require("../feature-libraries/index.js");
/**
 * Contains state and an internal API for managing {@link TreeNode}s.
 * @remarks All {@link TreeNode}s have an associated kernel object.
 * The kernel has the same lifetime as the node and spans both its unhydrated and hydrated states.
 * When hydration occurs, the kernel is notified via the {@link TreeNodeKernel.hydrate | hydrate} method.
 */
class TreeNodeKernel {
    constructor(node) {
        this.node = node;
        _TreeNodeKernel_hydrated.set(this, void 0);
        _TreeNodeKernel_events.set(this, (0, index_js_1.createEmitter)());
    }
    hydrate(anchorNode) {
        const offChildrenChanged = anchorNode.on("childrenChangedAfterBatch", () => {
            __classPrivateFieldGet(this, _TreeNodeKernel_events, "f").emit("nodeChanged");
        });
        const offSubtreeChanged = anchorNode.on("subtreeChangedAfterBatch", () => {
            __classPrivateFieldGet(this, _TreeNodeKernel_events, "f").emit("treeChanged");
        });
        const offAfterDestroy = anchorNode.on("afterDestroy", () => this.dispose());
        __classPrivateFieldSet(this, _TreeNodeKernel_hydrated, {
            anchorNode,
            offAnchorNode: () => {
                offChildrenChanged();
                offSubtreeChanged();
                offAfterDestroy();
            },
        }, "f");
    }
    dehydrate() {
        __classPrivateFieldGet(this, _TreeNodeKernel_hydrated, "f")?.offAnchorNode?.();
        __classPrivateFieldSet(this, _TreeNodeKernel_hydrated, undefined, "f");
    }
    isHydrated() {
        return __classPrivateFieldGet(this, _TreeNodeKernel_hydrated, "f") !== undefined;
    }
    getStatus() {
        if (__classPrivateFieldGet(this, _TreeNodeKernel_hydrated, "f")?.anchorNode === undefined) {
            return index_js_2.TreeStatus.New;
        }
        // TODO: Replace this check with the proper check against the cursor state when the cursor becomes part of the kernel
        const flex = __classPrivateFieldGet(this, _TreeNodeKernel_hydrated, "f").anchorNode.slots.get(index_js_2.flexTreeSlot);
        if (flex !== undefined) {
            (0, internal_1.assert)(flex instanceof index_js_2.LazyEntity, 0x9b4 /* Unexpected flex node implementation */);
            if (flex[index_js_2.isFreedSymbol]()) {
                return index_js_2.TreeStatus.Deleted;
            }
        }
        return (0, index_js_2.treeStatusFromAnchorCache)(__classPrivateFieldGet(this, _TreeNodeKernel_hydrated, "f").anchorNode);
    }
    on(eventName, listener) {
        return __classPrivateFieldGet(this, _TreeNodeKernel_events, "f").on(eventName, listener);
    }
    dispose() {
        this.dehydrate();
        // TODO: go to the context and remove myself from withAnchors
    }
}
exports.TreeNodeKernel = TreeNodeKernel;
_TreeNodeKernel_hydrated = new WeakMap(), _TreeNodeKernel_events = new WeakMap();
//# sourceMappingURL=treeNodeKernel.js.map