import '../../assert/js/assert.js';
import '../../globals.js';
import dotRandom from '../../dot/js/dotRandom.js';
import optionize from '../../phet-core/js/optionize.js';
import { DisplayedProperty } from '../../scenery/js/imports.js';
import joist from './joist.js';
class DisplayClickToDismissListener {
    /**
     * @param listener - The listener to be called when the Pointer goes up, likely to dismiss something.
     * @param [providedOptions]
     */
    constructor(listener, providedOptions) {
        // If optional displayedNode is provided, this property will be true when the displayedNode is 'displayed'. Controls
        // whether the listener is active and attaches to a Pointer.
        this.displayedProperty = null;
        const options = optionize()({
            displayedNode: null
        }, providedOptions);
        // The active Pointer for this listener, after a down event a subsequent up event on this Pointer will trigger
        // the behavior of `listener`.
        this.pointer = null;
        // A listener added to the Pointer on a down event which will do the work of `listener` when the pointer is
        // released. If this Pointer listener is interrupted we will never call the `listener`.
        this.pointerListener = {
            up: (event) => {
                listener(event);
                this.dismissPointer(this.pointer);
            },
            interrupt: () => {
                this.dismissPointer(this.pointer);
            },
            cancel: () => {
                this.dismissPointer(this.pointer);
            }
        };
        if (options.displayedNode) {
            this.displayedProperty = new DisplayedProperty(options.displayedNode);
        }
    }
    /**
     * Part of the scenery Input API.
     */
    down(event) {
        // When fuzz testing we want to exercise the component that is going to be dismissed so this should keep it up
        // long enough to hopefully receive some fuzzing.
        if (phet.chipper.isFuzzEnabled() && dotRandom.nextDouble() < 0.99) {
            return;
        }
        this.observePointer(event.pointer);
    }
    /**
     * Attach a listener to the Pointer that will watch when it goes up.
     */
    observePointer(pointer) {
        if (
        // Only observe one Pointer (for multitouch) and don't try to add a listener if the Pointer is already attached.
        this.pointer === null && !pointer.isAttached() &&
            // There is no displayedProperty, or it is true meaning the displayedNode is displayed.
            (this.displayedProperty === null || this.displayedProperty.value)) {
            this.pointer = pointer;
            this.pointer.addInputListener(this.pointerListener, true);
        }
    }
    /**
     * Remove the attached listener from the Pointer and clear it (if we are observing currently observing a Pointer).
     */
    dismissPointer(pointer) {
        if (this.pointer !== null) {
            assert && assert(this.pointerListener, 'There should be a pointerListener to remove.');
            this.pointer.removeInputListener(this.pointerListener);
            this.pointer = null;
        }
    }
    dispose() {
        this.dismissPointer(this.pointer);
        this.displayedProperty && this.displayedProperty.dispose();
    }
}
joist.register('DisplayClickToDismissListener', DisplayClickToDismissListener);
export default DisplayClickToDismissListener;
//# sourceMappingURL=DisplayClickToDismissListener.js.map