import '../../globals.js';
// Copyright 2021-2025, University of Colorado Boulder
/**
 * Singleton which keeps track of all async items currently loading, and doesn't proceed until all have been loaded.
 *
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 */
import affirm from '../../perennial-alias/js/browser-and-node/affirm.js';
import arrayRemove from '../../phet-core/js/arrayRemove.js';
import phetCore from './phetCore.js';
class AsyncLoader {
    constructor() {
        this.pendingLocks = [];
        this.loadComplete = false;
        this.listeners = [];
    }
    // Allow resetting this for sandbox or other non-sim purposes. We'll want to be able to load resources AFTER
    // we've completed loading.
    reset() {
        this.loadComplete = false;
    }
    /**
     * @param listener - called when load is complete
     */
    addListener(listener) {
        this.listeners.push(listener);
    }
    /**
     * Attempts to proceed to the next phase if possible (otherwise it's a no-op).
     */
    proceedIfReady() {
        if (this.pendingLocks.length === 0) {
            affirm(!this.loadComplete, 'cannot complete load twice');
            this.loadComplete = true;
            this.listeners.forEach(listener => listener());
        }
    }
    /**
     * Creates a lock, which is a callback that needs to be run before we can proceed.
     */
    createLock(object) {
        affirm(!this.loadComplete, 'Cannot create more locks after load-step has completed');
        this.pendingLocks.push(object);
        return () => {
            affirm(this.pendingLocks.includes(object), 'invalid lock');
            arrayRemove(this.pendingLocks, object);
            this.proceedIfReady();
        };
    }
}
const asyncLoader = new AsyncLoader();
phetCore.register('asyncLoader', asyncLoader);
export default asyncLoader;
//# sourceMappingURL=asyncLoader.js.map