"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = require("assert");
const sortedSegmentSet_1 = require("../sortedSegmentSet.cjs");
const ops_1 = require("../ops.cjs");
const mergeTreeTracking_1 = require("../mergeTreeTracking.cjs");
const testClient_1 = require("./testClient.cjs");
const segmentCount = 15;
function validateSorted(set, getOrdinal, prefix) {
    for (let i = 0; i < set.size - 1; i++) {
        const a = getOrdinal(set.items[i]);
        const b = getOrdinal(set.items[i + 1]);
        (0, assert_1.strict)(a !== undefined, `${prefix}: Undefined ordinal ${i}`);
        (0, assert_1.strict)(b !== undefined, `${prefix}: Undefined ordinal  ${i + 1}`);
        (0, assert_1.strict)(a <= b, `${prefix}: Not sorted at item ${i}`);
    }
}
function validateSet(client, set, getOrdinal) {
    validateSorted(set, getOrdinal, "initial");
    // add content to shift ordinals in tree
    for (let i = 0; i < segmentCount * 5; i++) {
        client.insertTextLocal((i * 3) % client.getLength(), `X`);
    }
    validateSorted(set, getOrdinal, "after insert");
    for (let i = set.size; set.size > 0; i += set.size) {
        // jump around the list a bit, so its not just an in-order remove
        const item = set.items[i % set.size];
        assert_1.strict.equal(set.remove(item), true, "remove failed");
        assert_1.strict.equal(set.has(item), false);
        validateSorted(set, getOrdinal, "during remove");
    }
}
describe("SortedSegmentSet", () => {
    const localUserLongId = "localUser";
    let client;
    beforeEach(() => {
        client = new testClient_1.TestClient();
        for (let i = 0; i < segmentCount; i++) {
            client.insertTextLocal(client.getLength(), i.toString()[0].repeat(i + 1));
        }
        client.startOrUpdateCollaboration(localUserLongId);
    });
    it("SortedSegmentSet of objects with segments", () => {
        const set = new sortedSegmentSet_1.SortedSegmentSet();
        for (let i = 0; i < client.getLength(); i++) {
            for (const pos of [i, client.getLength() - 1 - i]) {
                const segment = client.getContainingSegment(pos).segment;
                (0, assert_1.strict)(segment);
                const item = { segment };
                assert_1.strict.equal(set.has(item), false);
                set.addOrUpdate(item);
                assert_1.strict.equal(set.has(item), true);
            }
        }
        assert_1.strict.equal(set.size, client.getLength() * 2);
        validateSet(client, set, (i) => i.segment.ordinal);
    });
    it("SortedSegmentSet of segments", () => {
        const set = new sortedSegmentSet_1.SortedSegmentSet();
        for (let i = 0; i < client.getLength(); i++) {
            for (const pos of [i, client.getLength() - 1 - i]) {
                const segment = client.getContainingSegment(pos).segment;
                (0, assert_1.strict)(segment);
                set.addOrUpdate(segment);
                assert_1.strict.equal(set.has(segment), true);
            }
        }
        assert_1.strict.equal(set.size, segmentCount);
        validateSet(client, set, (i) => i.ordinal);
    });
    it("SortedSegmentSet of local references", () => {
        // using a sorted segment set directly creates problems,
        // as we don't correctly split, or merge, so leverage
        // the tracking group for correct behavior in those case
        // and spy it's internal set
        const set = new mergeTreeTracking_1.TrackingGroup();
        for (let i = 0; i < client.getLength(); i++) {
            for (const pos of [i, client.getLength() - 1 - i]) {
                const segmentInfo = client.getContainingSegment(pos);
                (0, assert_1.strict)(segmentInfo?.segment);
                const lref = client.createLocalReferencePosition(segmentInfo.segment, segmentInfo.offset, ops_1.ReferenceType.SlideOnRemove, undefined);
                assert_1.strict.equal(set.has(lref), false);
                set.link(lref);
                assert_1.strict.equal(set.has(lref), true);
            }
        }
        assert_1.strict.equal(set.size, client.getLength() * 2);
        validateSet(client, set.trackedSet, (i) => i.getSegment()?.ordinal);
    });
});
//# sourceMappingURL=sortedSegmentSet.spec.cjs.map