import '../../globals.js';
// Copyright 2019-2024, University of Colorado Boulder
/**
 * Timer so that other modules can run timing related code through the simulation's requestAnimationFrame. Use its
 * Emitter interface for adding/removing listeners.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
import axon from './axon.js';
import TinyEmitter from './TinyEmitter.js';
export default class Timer extends TinyEmitter {
    /**
     * Adds a listener to be called back once after the specified time in milliseconds
     * @param listener - called with no arguments
     * @param timeout in milliseconds
     * @returns an internally-wrapped listener which can be removed with clearTimeout
     */
    setTimeout(listener, timeout) {
        let elapsed = 0;
        const callback = (dt) => {
            elapsed += dt;
            // Convert seconds to ms and see if item has timed out
            if (elapsed * 1000 >= timeout) {
                // make sure that this callback hasn't already been removed by another listener while emit() is in progress
                if (this.hasListener(callback)) {
                    listener();
                    this.removeListener(callback);
                }
            }
        };
        this.addListener(callback);
        // Return the callback so it can be removed with removeStepListener
        return callback;
    }
    /**
     * Clear a scheduled timeout. If there was no timeout, nothing is done.
     */
    clearTimeout(listener) {
        if (this.hasListener(listener)) {
            this.removeListener(listener);
        }
    }
    /**
     * Adds a listener to be called at specified intervals (in milliseconds)
     * @param listener - called with no arguments
     * @param interval - in milliseconds
     * @returns an internally-wrapped listener which can be removed with clearInterval
     */
    setInterval(listener, interval) {
        let elapsed = 0;
        const callback = (dt) => {
            elapsed += dt;
            // Convert seconds to ms and see if item has timed out
            while (elapsed * 1000 >= interval && this.hasListener(callback)) {
                listener();
                elapsed = elapsed - interval / 1000.0; // Save the leftover time so it won't accumulate
            }
        };
        this.addListener(callback);
        // Return the callback so it can be removed if needed.
        return callback;
    }
    /**
     * Clear a scheduled interval. If there was no interval, nothing is done.
     */
    clearInterval(listener) {
        if (this.hasListener(listener)) {
            this.removeListener(listener);
        }
    }
    /**
     * Run a callback on the next frame. This method is largely for clarity.
     */
    runOnNextTick(listener) {
        this.setTimeout(listener, 0);
    }
}
axon.register('Timer', Timer);
//# sourceMappingURL=Timer.js.map