/** @import { TaskCallback, Task, TaskEntry } from '#client' */
import {
    raf
} from './timing.js';

// TODO move this into timing.js where it probably belongs

/**
 * @returns {void}
 */
function run_tasks() {
    // use `raf.now()` instead of the `requestAnimationFrame` callback argument, because
    // otherwise things can get wonky https://github.com/sveltejs/svelte/pull/14541
    const now = raf.now();

    raf.tasks.forEach((task) => {
        if (!task.c(now)) {
            raf.tasks.delete(task);
            task.f();
        }
    });

    if (raf.tasks.size !== 0) {
        raf.tick(run_tasks);
    }
}

/**
 * Creates a new task that runs on each raf frame
 * until it returns a falsy value or is aborted
 * @param {TaskCallback} callback
 * @returns {Task}
 */
export function loop(callback) {
    /** @type {TaskEntry} */
    let task;

    if (raf.tasks.size === 0) {
        raf.tick(run_tasks);
    }

    return {
        promise: new Promise((fulfill) => {
            raf.tasks.add((task = {
                c: callback,
                f: fulfill
            }));
        }),
        abort() {
            raf.tasks.delete(task);
        }
    };
}