import '../../../assert/js/assert.js';
import '../../../globals.js';
// Copyright 2017-2024, University of Colorado Boulder
/**
 * Base type for controllers that create and keep an SVG gradient element up-to-date with a Scenery gradient.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import cleanArray from '../../../phet-core/js/cleanArray.js';
import { scenery, SVGGradientStop } from '../imports.js';
export default class SVGGradient {
    constructor(svgBlock, gradient) {
        this.initialize(svgBlock, gradient);
    }
    isActiveSVGGradient() { return !!this.svgBlock; }
    initialize(svgBlock, gradient) {
        sceneryLog && sceneryLog.Paints && sceneryLog.Paints(`[SVGGradient] initialize ${gradient.id}`);
        sceneryLog && sceneryLog.Paints && sceneryLog.push();
        this.svgBlock = svgBlock;
        this.gradient = gradient;
        const hasPreviousDefinition = this.definition !== undefined;
        this.definition = this.definition || this.createDefinition();
        if (!hasPreviousDefinition) {
            // so we don't depend on the bounds of the object being drawn with the gradient
            this.definition.setAttribute('gradientUnits', 'userSpaceOnUse');
        }
        if (gradient.transformMatrix) {
            this.definition.setAttribute('gradientTransform', gradient.transformMatrix.getSVGTransform());
        }
        else {
            this.definition.removeAttribute('gradientTransform');
        }
        // We need to make a function call, as stops need to be rescaled/reversed in some radial gradient cases.
        const gradientStops = gradient.getSVGStops();
        this.stops = cleanArray(this.stops);
        for (let i = 0; i < gradientStops.length; i++) {
            const stop = new SVGGradientStop(this, gradientStops[i].ratio, gradientStops[i].color);
            this.stops.push(stop);
            this.definition.appendChild(stop.svgElement);
        }
        this.dirty = false;
        sceneryLog && sceneryLog.Paints && sceneryLog.pop();
    }
    /**
     * Called from SVGGradientStop when a stop needs to change the actual color.
     */
    markDirty() {
        if (!this.dirty) {
            assert && assert(this.isActiveSVGGradient());
            const activeGradient = this;
            sceneryLog && sceneryLog.Paints && sceneryLog.Paints(`[SVGGradient] switched to dirty: ${this.gradient.id}`);
            sceneryLog && sceneryLog.Paints && sceneryLog.push();
            this.dirty = true;
            activeGradient.svgBlock.markDirtyGradient(this);
            sceneryLog && sceneryLog.Paints && sceneryLog.pop();
        }
    }
    /**
     * Called from SVGBlock when we need to update our color stops.
     */
    update() {
        if (!this.dirty) {
            return;
        }
        this.dirty = false;
        sceneryLog && sceneryLog.Paints && sceneryLog.Paints(`[SVGGradient] update: ${this.gradient.id}`);
        sceneryLog && sceneryLog.Paints && sceneryLog.push();
        for (let i = 0; i < this.stops.length; i++) {
            this.stops[i].update();
        }
        sceneryLog && sceneryLog.Paints && sceneryLog.pop();
    }
    /**
     * Disposes, so that it can be reused from the pool.
     */
    dispose() {
        sceneryLog && sceneryLog.Paints && sceneryLog.Paints(`[SVGGradient] dispose ${this.gradient.id}`);
        sceneryLog && sceneryLog.Paints && sceneryLog.push();
        // Dispose and clean up stops
        for (let i = 0; i < this.stops.length; i++) {
            const stop = this.stops[i]; // SVGGradientStop
            this.definition.removeChild(stop.svgElement);
            stop.dispose();
        }
        cleanArray(this.stops);
        this.svgBlock = null;
        this.gradient = null;
        this.freeToPool();
        sceneryLog && sceneryLog.Paints && sceneryLog.pop();
    }
}
scenery.register('SVGGradient', SVGGradient);
//# sourceMappingURL=SVGGradient.js.map