import '../../../globals.js';
import { Shape } from '../../../kite/js/imports.js';
import optionize from '../../../phet-core/js/optionize.js';
import { Node, Renderer, scenery, SpritesCanvasDrawable, SpritesWebGLDrawable } from '../imports.js';
export default class Sprites extends Node {
    constructor(providedOptions) {
        const options = optionize()({
            sprites: [],
            spriteInstances: [],
            hitTestSprites: false,
            // Sets the node's default renderer to WebGL (as we'll generally want that when using this type)
            renderer: 'webgl'
        }, providedOptions);
        super();
        this._sprites = options.sprites;
        this._spriteInstances = options.spriteInstances;
        this._hitTestSprites = options.hitTestSprites;
        // WebGL and Canvas are supported.
        this.setRendererBitmask(Renderer.bitmaskCanvas | Renderer.bitmaskWebGL);
        this.mutate(options);
    }
    /**
     * Sets the bounds that are used for layout/repainting.
     *
     * These bounds should always cover at least the area where the Sprites will draw in. If this is violated, this
     * node may be partially or completely invisible in Scenery's output.
     */
    setCanvasBounds(selfBounds) {
        this.invalidateSelf(selfBounds);
    }
    set canvasBounds(value) { this.setCanvasBounds(value); }
    get canvasBounds() { return this.getCanvasBounds(); }
    /**
     * Returns the previously-set canvasBounds, or Bounds2.NOTHING if it has not been set yet.
     */
    getCanvasBounds() {
        return this.getSelfBounds();
    }
    /**
     * Draws the current Node's self representation, assuming the wrapper's Canvas context is already in the local
     * coordinate frame of this node.
     *
     * @param wrapper
     * @param matrix - The transformation matrix already applied to the context.
     */
    canvasPaintSelf(wrapper, matrix) {
        SpritesCanvasDrawable.prototype.paintCanvas(wrapper, this, matrix);
    }
    /**
     * Creates a Canvas drawable for this Sprites node. (scenery-internal)
     *
     * @param renderer - In the bitmask format specified by Renderer, which may contain additional bit flags.
     * @param instance - Instance object that will be associated with the drawable
     */
    createCanvasDrawable(renderer, instance) {
        // @ts-expect-error Pooling
        return SpritesCanvasDrawable.createFromPool(renderer, instance);
    }
    /**
     * Creates a WebGL drawable for this Image. (scenery-internal)
     *
     * @param renderer - In the bitmask format specified by Renderer, which may contain additional bit flags.
     * @param instance - Instance object that will be associated with the drawable
     */
    createWebGLDrawable(renderer, instance) {
        // @ts-expect-error Pooling
        return SpritesWebGLDrawable.createFromPool(renderer, instance);
    }
    /**
     * Computes whether the provided point is "inside" (contained) in this Node's self content, or "outside".
     *
     * @param point - Considered to be in the local coordinate frame
     */
    containsPointSelf(point) {
        const inBounds = super.containsPointSelf(point);
        if (!inBounds) {
            return false;
        }
        if (this._hitTestSprites) {
            return !!this.getSpriteInstanceFromPoint(point);
        }
        else {
            return true;
        }
    }
    /**
     * Finds which sprite instance is on top under a certain point (or null if none are).
     */
    getSpriteInstanceFromPoint(point) {
        for (let i = this._spriteInstances.length - 1; i >= 0; i--) {
            if (this._spriteInstances[i].containsPoint(point)) {
                return this._spriteInstances[i];
            }
        }
        return null;
    }
    /**
     * Returns a Shape that represents the area covered by containsPointSelf.
     */
    getSelfShape() {
        if (this._hitTestSprites) {
            return Shape.union(this._spriteInstances.map(instance => instance.getShape()));
        }
        else {
            return Shape.bounds(this.selfBounds);
        }
    }
    /**
     * Whether this Node itself is painted (displays something itself).
     */
    isPainted() {
        // Always true for Sprites nodes
        return true;
    }
    /**
     * Should be called when this node needs to be repainted. When not called, Scenery assumes that this node does
     * NOT need to be repainted (although Scenery may repaint it due to other nodes needing to be repainted).
     *
     * This sets a "dirty" flag, so that it will be repainted the next time it would be displayed.
     */
    invalidatePaint() {
        const stateLen = this._drawables.length;
        for (let i = 0; i < stateLen; i++) {
            this._drawables[i].markDirty();
        }
    }
    mutate(options) {
        return super.mutate(options);
    }
}
/**
 * {Array.<string>} - String keys for all the allowed options that will be set by node.mutate( options ), in the
 * order they will be evaluated in.
 *
 * NOTE: See Node's _mutatorKeys documentation for more information on how this operates, and potential special
 *       cases that may apply.
 */
Sprites.prototype._mutatorKeys = ['canvasBounds'].concat(Node.prototype._mutatorKeys);
scenery.register('Sprites', Sprites);
//# sourceMappingURL=Sprites.js.map