"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.APIQueue = void 0;
const sleep_1 = require("../utils/sleep");
class APIQueue {
    constructor(api) {
        this.api = api;
        this.running = false;
        this.queue = [];
    }
    start(id, date = new Date()) {
        this.getItem(id).start = { date };
    }
    progress(id, buffer) {
        const item = this.getItem(id);
        if (item.progress) {
            item.progress.chunks.push(buffer);
        }
        else {
            item.progress = { chunks: [buffer] };
        }
    }
    complete(id, success, date = new Date()) {
        this.getItem(id).complete = { date, success };
    }
    async wait(fn) {
        this.running = true;
        try {
            if (fn) {
                await Promise.all([fn(), this.wait()]);
            }
            else {
                while (this.running) {
                    await (0, sleep_1.sleep)(500);
                    await this.flush();
                }
                await this.flush();
            }
        }
        finally {
            this.running = false;
        }
    }
    getItem(id) {
        const item = this.queue.find((i) => i.id === id);
        if (item) {
            return item;
        }
        else {
            const item = { id };
            this.queue.push(item);
            return item;
        }
    }
    async flush() {
        do {
            this.queue = this.queue.filter((update) => update.start || update.progress || update.complete);
            const update = this.queue.shift();
            if (!update) {
                break;
            }
            if (update.start) {
                const { date } = update.start;
                delete update.start;
                await this.api.start(update.id, date);
            }
            if (update.progress) {
                const buffer = Buffer.concat(update.progress.chunks);
                delete update.progress;
                await this.api.progress(update.id, buffer);
            }
            if (update.complete) {
                const { date, success } = update.complete;
                delete update.complete;
                await this.api.complete(update.id, date, success);
            }
        } while (this.queue.length);
    }
}
exports.APIQueue = APIQueue;
//# sourceMappingURL=api-queue.js.map