export class TokenStreamRegulator {
    /** @internal */ _queue = [];
    addChunk({ tokens, text }) {
        const queuedRelease = QueuedTokenRelease._create(tokens, text);
        this._queue.push(queuedRelease);
        return queuedRelease;
    }
    popFreeChunkTokens() {
        const res = [];
        while (this._queue.length > 0 && this._queue[0].isFree)
            res.push(...this._queue.shift().tokens);
        return res;
    }
    getPartiallyFreeChunk() {
        if (this._queue.length > 0 && this._queue[0].isPartiallyFree) {
            const queuedRelease = this._queue[0];
            return {
                tokens: queuedRelease.tokens.slice(0, queuedRelease.getFreeTokenIndex()),
                text: queuedRelease.text.slice(0, queuedRelease.getFreeTextIndex())
            };
        }
        return {
            tokens: [],
            text: ""
        };
    }
    getAllQueuedChunkTokens() {
        return this._queue.flatMap((queuedRelease) => queuedRelease.tokens);
    }
}
export class QueuedTokenRelease {
    /** @internal */ _textLocks = new Set();
    /** @internal */ _tokenLocks = new Set();
    tokens;
    text;
    constructor(tokens, text) {
        this.tokens = tokens;
        this.text = text;
    }
    get isFree() {
        return this._textLocks.size === 0 && this._tokenLocks.size === 0;
    }
    get isPartiallyFree() {
        return this._textLocks.size !== 0 && this._tokenLocks.size !== 0;
    }
    getFreeTextIndex() {
        if (this._textLocks.size === 0)
            return this.text.length;
        return [...this._textLocks]
            .reduce((res, lock) => Math.min(res, lock.index), this.text.length);
    }
    getFreeTokenIndex() {
        if (this._tokenLocks.size === 0)
            return this.tokens.length;
        return [...this._tokenLocks]
            .reduce((res, lock) => Math.min(res, lock.index), this.tokens.length);
    }
    createTextIndexLock(startIndex) {
        const lock = QueuedTokenReleaseLock._create(startIndex, this._textLocks);
        if (startIndex >= 0 && startIndex < this.text.length)
            this._textLocks.add(lock);
        return lock;
    }
    createTokenIndexLock(startIndex) {
        const lock = QueuedTokenReleaseLock._create(startIndex, this._tokenLocks);
        if (startIndex >= 0 && startIndex < this.tokens.length)
            this._tokenLocks.add(lock);
        return lock;
    }
    /** @internal */
    static _create(tokens, text) {
        return new QueuedTokenRelease(tokens, text);
    }
}
export class QueuedTokenReleaseLock {
    /** @internal */ _index;
    /** @internal */ _locks;
    constructor(index, locks) {
        this._index = index;
        this._locks = locks;
    }
    get index() {
        return this._index;
    }
    dispose() {
        this._locks.delete(this);
    }
    [Symbol.dispose]() {
        this.dispose();
    }
    /** @internal */
    static _create(length, locks) {
        return new QueuedTokenReleaseLock(length, locks);
    }
}
//# sourceMappingURL=TokenStreamRegulator.js.map