"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildNodeComparator = void 0;
const index_js_1 = require("../core/index.js");
/**
 * creates a FieldComparator that checks a field has the expected number of
 *
 * @remarks
 * The returned comparator checks that the field has the expected number of children
 * and that each child node matches the corresponding comparator.
 */
function buildFieldComparator(nodeComparators) {
    const expectedLength = nodeComparators.length;
    return (cursor) => {
        if (cursor.getFieldLength() !== expectedLength) {
            return false;
        }
        for (let inNodes = cursor.firstNode(); inNodes; inNodes = cursor.nextNode()) {
            const comparator = nodeComparators[cursor.fieldIndex];
            if (comparator?.(cursor) !== true) {
                cursor.exitNode();
                return false;
            }
        }
        return true;
    };
}
/**
 * Walks the cursor at its current node position and builds a comparator that can test whether another
 * cursor position has the same structure and values.
 *
 * @remarks
 * Fields are compared by key (not iteration order), so this is safe regardless of cursor field ordering.
 * Missing fields in the compared node will cause a mismatch.
 *
 * The cursor must be in Nodes mode. After this call, the cursor is restored to its original position.
 *
 */
function buildNodeComparator(cursor) {
    const expectedValue = cursor.value;
    if (expectedValue !== undefined) {
        return (other) => Object.is(other.value, expectedValue);
    }
    const fieldComparators = (0, index_js_1.mapCursorFields)(cursor, (fieldCursor) => ({
        key: fieldCursor.getFieldKey(),
        compare: buildFieldComparator((0, index_js_1.mapCursorField)(fieldCursor, buildNodeComparator)),
    }));
    return (other) => {
        if (!Object.is(other.value, expectedValue)) {
            return false;
        }
        for (const { key, compare } of fieldComparators) {
            if (!(0, index_js_1.inCursorField)(other, key, () => compare(other))) {
                return false;
            }
        }
        return true;
    };
}
exports.buildNodeComparator = buildNodeComparator;
//# sourceMappingURL=cursorComparator.js.map