import '../../../assert/js/assert.js';
import '../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * RenderProgram for normalizing the result of another RenderProgram
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import Vector4 from '../../../dot/js/Vector4.js';
import { alpenglow, RenderColor, RenderInstruction, RenderPathBoolean, RenderProgram } from '../imports.js';
export default class RenderNormalize extends RenderProgram {
    constructor(program) {
        super([program], program.isFullyTransparent, program.isFullyOpaque);
        this.program = program;
    }
    getName() {
        return 'RenderNormalize';
    }
    withChildren(children) {
        assert && assert(children.length === 1);
        return new RenderNormalize(children[0]);
    }
    getSimplified(children) {
        const program = children[0];
        if (program.isFullyTransparent) {
            return RenderColor.TRANSPARENT;
        }
        else if (program instanceof RenderColor) {
            return new RenderColor(program.color.magnitude > 0 ? program.color.normalized() : Vector4.ZERO);
        }
        // Move our path-booleans "up" to the top level (so we can combine other things AND improve path-boolean replacement performance)
        else if (program instanceof RenderPathBoolean && program.isOneSided()) {
            return program.withOneSide(this.withChildren([program.getOneSide()])).simplified();
        }
        else {
            return null;
        }
    }
    evaluate(context) {
        const source = this.program.evaluate(context);
        const magnitude = source.magnitude;
        if (magnitude === 0) {
            return Vector4.ZERO;
        }
        else {
            assert && assert(source.normalized().isFinite());
            return source.normalized();
        }
    }
    writeInstructions(instructions) {
        this.program.writeInstructions(instructions);
        instructions.push(RenderInstructionNormalize.INSTANCE);
    }
    serialize() {
        return {
            type: 'RenderNormalize',
            program: this.program.serialize()
        };
    }
    static deserialize(obj) {
        return new RenderNormalize(RenderProgram.deserialize(obj.program));
    }
}
alpenglow.register('RenderNormalize', RenderNormalize);
const scratchVector = new Vector4(0, 0, 0, 0);
export class RenderInstructionNormalize extends RenderInstruction {
    toString() {
        return 'RenderInstructionNormalize()';
    }
    equals(other, areLocationsEqual) {
        return other instanceof RenderInstructionNormalize;
    }
    execute(stack, context, executor) {
        stack.readTop(scratchVector);
        const magnitude = scratchVector.magnitude;
        if (magnitude === 0) {
            stack.writeTop(Vector4.ZERO);
        }
        else {
            stack.writeTopValues(scratchVector.x / magnitude, scratchVector.y / magnitude, scratchVector.z / magnitude, scratchVector.w / magnitude);
        }
    }
    writeBinary(encoder, getOffset) {
        encoder.pushU32(RenderInstruction.NormalizeCode);
    }
    getBinaryLength() {
        return 1;
    }
}
RenderInstructionNormalize.INSTANCE = new RenderInstructionNormalize();
//# sourceMappingURL=RenderNormalize.js.map