import '../../../globals.js';
import { alpenglow, RenderColor, RenderLinearDisplayP3ToLinearSRGB, RenderLinearSRGBToLinearDisplayP3, RenderLinearSRGBToOklab, RenderLinearSRGBToSRGB, RenderOklabToLinearSRGB, RenderPathBoolean, RenderPremultiply, RenderProgram, RenderSRGBToLinearSRGB, RenderUnpremultiply } from '../imports.js';
export default class RenderColorSpaceConversion extends RenderProgram {
    constructor(program, convert) {
        super([program], program.isFullyTransparent, program.isFullyOpaque);
        this.program = program;
        this.convert = convert;
    }
    // TODO: add a helper on RenderProgram
    static convert(renderProgram, fromSpace, toSpace) {
        if (fromSpace === toSpace) {
            return renderProgram;
        }
        if (fromSpace.isPremultiplied) {
            renderProgram = new RenderUnpremultiply(renderProgram);
        }
        if (!fromSpace.isLinear) {
            renderProgram = fromSpace.toLinearRenderProgram(renderProgram);
        }
        renderProgram = fromSpace.linearToLinearSRGBRenderProgram(renderProgram);
        renderProgram = toSpace.linearSRGBToLinearRenderProgram(renderProgram);
        if (!toSpace.isLinear) {
            renderProgram = toSpace.fromLinearRenderProgram(renderProgram);
        }
        if (toSpace.isPremultiplied) {
            renderProgram = new RenderPremultiply(renderProgram);
        }
        return renderProgram.simplified();
    }
    getSimplified(children) {
        const program = children[0];
        if (program.isFullyTransparent) {
            return RenderColor.TRANSPARENT;
        }
        else if (program instanceof RenderColor) {
            return new RenderColor(this.convert(program.color));
        }
        else if (this.inverse && program instanceof this.inverse) {
            return program.program;
        }
        // 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);
        return this.convert(source);
    }
    static displayP3ToSRGB(renderProgram) {
        return new RenderLinearSRGBToSRGB(new RenderLinearDisplayP3ToLinearSRGB(new RenderSRGBToLinearSRGB(renderProgram)));
    }
    static sRGBToDisplayP3(renderProgram) {
        return new RenderLinearSRGBToSRGB(new RenderLinearSRGBToLinearDisplayP3(new RenderSRGBToLinearSRGB(renderProgram)));
    }
    static displayP3ToLinearSRGB(renderProgram) {
        return new RenderLinearDisplayP3ToLinearSRGB(new RenderSRGBToLinearSRGB(renderProgram));
    }
    static linearSRGBToDisplayP3(renderProgram) {
        return new RenderLinearSRGBToSRGB(new RenderLinearSRGBToLinearDisplayP3(renderProgram));
    }
    static oklabToSRGB(renderProgram) {
        return new RenderLinearSRGBToSRGB(new RenderOklabToLinearSRGB(renderProgram));
    }
    static sRGBToOklab(renderProgram) {
        return new RenderLinearSRGBToOklab(new RenderSRGBToLinearSRGB(renderProgram));
    }
    static oklabToDisplayP3(renderProgram) {
        return new RenderLinearSRGBToSRGB(new RenderLinearSRGBToLinearDisplayP3(new RenderOklabToLinearSRGB(renderProgram)));
    }
    static displayP3ToOklab(renderProgram) {
        return new RenderLinearSRGBToOklab(new RenderLinearDisplayP3ToLinearSRGB(new RenderSRGBToLinearSRGB(renderProgram)));
    }
    static premulSRGBToPremulLinearSRGB(renderProgram) {
        return new RenderPremultiply(new RenderSRGBToLinearSRGB(new RenderUnpremultiply(renderProgram)));
    }
    static premulLinearSRGBToPremulSRGB(renderProgram) {
        return new RenderPremultiply(new RenderLinearSRGBToSRGB(new RenderUnpremultiply(renderProgram)));
    }
    static premulLinearSRGBToPremulDisplayP3(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.linearSRGBToDisplayP3(new RenderUnpremultiply(renderProgram)));
    }
    static premulDisplayP3ToPremulLinearSRGB(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.displayP3ToLinearSRGB(new RenderUnpremultiply(renderProgram)));
    }
    static premulDisplayP3ToPremulSRGB(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.displayP3ToSRGB(new RenderUnpremultiply(renderProgram)));
    }
    static premulSRGBToPremulDisplayP3(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.sRGBToDisplayP3(new RenderUnpremultiply(renderProgram)));
    }
    static premulOklabToPremulSRGB(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.oklabToSRGB(new RenderUnpremultiply(renderProgram)));
    }
    static premulSRGBToPremulOklab(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.sRGBToOklab(new RenderUnpremultiply(renderProgram)));
    }
    static premulOklabToPremulDisplayP3(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.oklabToDisplayP3(new RenderUnpremultiply(renderProgram)));
    }
    static premulDisplayP3ToPremulOklab(renderProgram) {
        return new RenderPremultiply(RenderColorSpaceConversion.displayP3ToOklab(new RenderUnpremultiply(renderProgram)));
    }
    serialize() {
        return {
            type: 'RenderColorSpaceConversion',
            subtype: this.getName(),
            program: this.program.serialize()
        };
    }
    static deserialize(obj) {
        const program = RenderProgram.deserialize(obj.program);
        if (obj.subtype === 'RenderPremultiply') {
            return new RenderPremultiply(program);
        }
        else if (obj.subtype === 'RenderUnpremultiply') {
            return new RenderUnpremultiply(program);
        }
        else if (obj.subtype === 'RenderLinearSRGBToOklab') {
            return new RenderLinearSRGBToOklab(program);
        }
        else if (obj.subtype === 'RenderLinearSRGBToSRGB') {
            return new RenderLinearSRGBToSRGB(program);
        }
        else if (obj.subtype === 'RenderOklabToLinearSRGB') {
            return new RenderOklabToLinearSRGB(program);
        }
        else if (obj.subtype === 'RenderSRGBToLinearSRGB') {
            return new RenderSRGBToLinearSRGB(program);
        }
        else if (obj.subtype === 'RenderLinearDisplayP3ToLinearSRGB') {
            return new RenderLinearDisplayP3ToLinearSRGB(program);
        }
        else if (obj.subtype === 'RenderLinearSRGBToLinearDisplayP3') {
            return new RenderLinearSRGBToLinearDisplayP3(program);
        }
        else {
            throw new Error(`Unrecognized subtype: ${obj.subtype}`);
        }
    }
}
alpenglow.register('RenderColorSpaceConversion', RenderColorSpaceConversion);
//# sourceMappingURL=RenderColorSpaceConversion.js.map