"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoizedIdRangeAllocator = void 0;
const index_js_1 = require("../util/index.js");
/**
 * @internal
 */
exports.MemoizedIdRangeAllocator = {
    fromNextId(nextId = 0) {
        const rangeMap = new Map();
        let _nextId = nextId;
        return {
            allocate(key, startId, length) {
                let count = length ?? 1;
                const out = [];
                const ranges = (0, index_js_1.getOrAddEmptyToMap)(rangeMap, key);
                let currId = startId;
                while (count > 0) {
                    const firstRange = (0, index_js_1.getFirstEntryFromRangeMap)(ranges, currId, count);
                    if (firstRange === undefined) {
                        const newId = _nextId;
                        _nextId += count;
                        (0, index_js_1.setInRangeMap)(ranges, currId, count, newId);
                        out.push({ first: (0, index_js_1.brand)(newId), count });
                        count = 0;
                    }
                    else {
                        const idRange = {
                            first: (0, index_js_1.brand)(firstRange.value),
                            count: firstRange.length,
                        };
                        if (currId < firstRange.start) {
                            const countToAdd = firstRange.start - currId;
                            (0, index_js_1.setInRangeMap)(ranges, currId, countToAdd, _nextId);
                            out.push({ first: (0, index_js_1.brand)(_nextId), count: countToAdd });
                            _nextId += countToAdd;
                            currId += countToAdd;
                            count -= countToAdd;
                        }
                        else if (firstRange.start < currId) {
                            const countToTrim = currId - firstRange.start;
                            idRange.first = (0, index_js_1.brand)(idRange.first + countToTrim);
                            idRange.count -= countToTrim;
                        }
                        if (idRange.count > count) {
                            idRange.count = count;
                        }
                        else if (idRange.count < count &&
                            firstRange.value + firstRange.length === _nextId) {
                            // The existing range can be extended
                            _nextId += count - idRange.count;
                            firstRange.length = count;
                            idRange.count = count;
                        }
                        out.push(idRange);
                        count -= idRange.count;
                        currId += idRange.count;
                    }
                }
                return out;
            },
            mint(length) {
                const count = length ?? 1;
                const out = _nextId;
                _nextId += count;
                return (0, index_js_1.brand)(out);
            },
        };
    },
};
//# sourceMappingURL=memoizedIdRangeAllocator.js.map