"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
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 __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 _LazyEntity_lazyCursor;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LazyEntity = exports.anchorSymbol = exports.cursorSymbol = exports.forgetAnchorSymbol = exports.tryMoveCursorToAnchorSymbol = exports.isFreedSymbol = exports.prepareForEditSymbol = exports.makePrivatePropertyNotEnumerable = exports.makePropertyNotEnumerable = exports.makePropertyEnumerableOwn = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const core_1 = require("../../core");
const util_1 = require("../../util");
const editableTreeTypes_1 = require("./editableTreeTypes");
/**
 * Declare an enumerable own property on `T` under the key `key` using the implementation of one on `from`.
 */
function makePropertyEnumerableOwn(target, key, from) {
    (0, core_utils_1.assert)(Object.getOwnPropertyDescriptor(target, key) === undefined, 0x776 /* preexisting property */);
    const descriptor = Object.getOwnPropertyDescriptor(from, key) ?? (0, util_1.fail)("missing property");
    Object.defineProperty(target, key, { ...descriptor, enumerable: true });
}
exports.makePropertyEnumerableOwn = makePropertyEnumerableOwn;
/**
 * Modify a property on `T` under the key `key` to be not-enumerable
 */
function makePropertyNotEnumerable(target, key) {
    makePrivatePropertyNotEnumerable(target, key);
}
exports.makePropertyNotEnumerable = makePropertyNotEnumerable;
/**
 * Like {@link makePropertyNotEnumerable}, but less type safe so it works on private properties.
 */
function makePrivatePropertyNotEnumerable(target, key) {
    (0, core_utils_1.assert)(Object.getOwnPropertyDescriptor(target, key)?.enumerable === true, 0x777 /* missing property or not enumerable */);
    Object.defineProperty(target, key, { enumerable: false });
}
exports.makePrivatePropertyNotEnumerable = makePrivatePropertyNotEnumerable;
exports.prepareForEditSymbol = Symbol("prepareForEdit");
exports.isFreedSymbol = Symbol("isFreed");
exports.tryMoveCursorToAnchorSymbol = Symbol("tryMoveCursorToAnchor");
exports.forgetAnchorSymbol = Symbol("forgetAnchor");
exports.cursorSymbol = Symbol("cursor");
exports.anchorSymbol = Symbol("anchor");
/**
 * This is a base class for lazy (cursor based) UntypedEntity implementations, which uniformly handles cursors and anchors.
 */
class LazyEntity {
    constructor(context, schema, cursor, anchor) {
        this.context = context;
        this.schema = schema;
        _LazyEntity_lazyCursor.set(this, void 0);
        this[exports.anchorSymbol] = anchor;
        __classPrivateFieldSet(this, _LazyEntity_lazyCursor, cursor.fork(), "f");
        context.withCursors.add(this);
        this.context.withAnchors.add(this);
        // Setup JS Object API:
        makePropertyNotEnumerable(this, "context");
        makePropertyNotEnumerable(this, "schema");
        makePropertyNotEnumerable(this, exports.anchorSymbol);
    }
    [(_LazyEntity_lazyCursor = new WeakMap(), util_1.disposeSymbol)]() {
        __classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f").free();
        this.context.withCursors.delete(this);
        this[exports.forgetAnchorSymbol](this[exports.anchorSymbol]);
        this.context.withAnchors.delete(this);
    }
    [exports.prepareForEditSymbol]() {
        __classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f").clear();
        this.context.withCursors.delete(this);
    }
    [exports.isFreedSymbol]() {
        return __classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f").state === core_1.ITreeSubscriptionCursorState.Freed;
    }
    get [exports.cursorSymbol]() {
        if (__classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f").state !== core_1.ITreeSubscriptionCursorState.Current) {
            (0, core_utils_1.assert)(__classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f").state === core_1.ITreeSubscriptionCursorState.Cleared, 0x778 /* Unset cursor should be in cleared state */);
            (0, core_utils_1.assert)(this[exports.anchorSymbol] !== undefined, 0x779 /* EditableTree should have an anchor if it does not have a cursor */);
            const result = this[exports.tryMoveCursorToAnchorSymbol](this[exports.anchorSymbol], __classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f"));
            (0, core_utils_1.assert)(result === 1 /* TreeNavigationResult.Ok */, 0x77a /* It is invalid to access an EditableTree node which no longer exists */);
            this.context.withCursors.add(this);
        }
        return __classPrivateFieldGet(this, _LazyEntity_lazyCursor, "f");
    }
}
exports.LazyEntity = LazyEntity;
/**
 * Prevent Entities from inheriting members from Object.prototype including:
 * '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__',
 * 'hasOwnProperty', 'isPrototypeOf', 'valueOf', 'propertyIsEnumerable', 'toLocaleString' and 'toString'.
 *
 * This opens up more options for field names on struct nodes.
 */
Object.setPrototypeOf(LazyEntity.prototype, null);
//# sourceMappingURL=lazyEntity.js.map