/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { brand, getFirstEntryFromRangeMap, getOrAddEmptyToMap, setInRangeMap, } from "../util/index.js";
/**
 * @internal
 */
export const MemoizedIdRangeAllocator = {
    fromNextId(nextId = 0) {
        const rangeMap = new Map();
        let _nextId = nextId;
        return {
            allocate(key, startId, length) {
                let count = length ?? 1;
                const out = [];
                const ranges = getOrAddEmptyToMap(rangeMap, key);
                let currId = startId;
                while (count > 0) {
                    const firstRange = getFirstEntryFromRangeMap(ranges, currId, count);
                    if (firstRange === undefined) {
                        const newId = _nextId;
                        _nextId += count;
                        setInRangeMap(ranges, currId, count, newId);
                        out.push({ first: brand(newId), count });
                        count = 0;
                    }
                    else {
                        const idRange = {
                            first: brand(firstRange.value),
                            count: firstRange.length,
                        };
                        if (currId < firstRange.start) {
                            const countToAdd = firstRange.start - currId;
                            setInRangeMap(ranges, currId, countToAdd, _nextId);
                            out.push({ first: brand(_nextId), count: countToAdd });
                            _nextId += countToAdd;
                            currId += countToAdd;
                            count -= countToAdd;
                        }
                        else if (firstRange.start < currId) {
                            const countToTrim = currId - firstRange.start;
                            idRange.first = 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 brand(out);
            },
        };
    },
};
//# sourceMappingURL=memoizedIdRangeAllocator.js.map