var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MODULES } from "../../../engine/engine_modules.js";
import { serializable } from "../../../engine/engine_serialization.js";
import { nameToThreeTonemapping } from "../../../engine/engine_tonemapping.js";
import { getParam } from "../../../engine/engine_utils.js";
import { PostProcessingEffect } from "../PostProcessingEffect.js";
import { findPostProcessingManager } from "../utils.js";
import { VolumeParameter } from "../VolumeParameter.js";
import { registerCustomEffectType } from "../VolumeProfile.js";
import { NEToneMappingMode, threeToNeedleToneMapping, threeToneMappingToEffectMode, toThreeToneMapping } from "./Tonemapping.utils.js";
const debug = getParam("debugpost");
/**
 * [ToneMappingEffect](https://engine.needle.tools/docs/api/ToneMappingEffect) adjusts the brightness and contrast of the rendered scene to map high dynamic range (HDR) colors to a displayable range.
 * This effect is essential for achieving realistic lighting and color representation in 3D scenes, as it helps to preserve details in both bright and dark areas.
 * Various tonemapping algorithms can be applied to achieve different visual styles and effects.
 * @summary Tonemapping Post-Processing Effect
 * @category Effects
 * @group Components
 */
export class ToneMappingEffect extends PostProcessingEffect {
    get typeName() {
        return "ToneMapping";
    }
    mode = new VolumeParameter(undefined);
    exposure = new VolumeParameter(1);
    /** Set the tonemapping mode to e.g. "agx" */
    setMode(mode) {
        const enumValue = NEToneMappingMode[mode];
        if (enumValue === undefined) {
            console.error("[PostProcessing] Invalid ToneMapping mode", mode);
            return this;
        }
        this.mode.value = enumValue;
        return this;
    }
    get isToneMapping() { return true; }
    onEffectEnabled() {
        // Tonemapping works with and without a postprocessing manager. 
        // If there's no manager already in the scene we don't need to create one because tonemapping can also be applied without a postprocessing pass
        const ppmanager = findPostProcessingManager(this);
        if (!ppmanager)
            return;
        super.onEffectEnabled(ppmanager);
    }
    _tonemappingEffect = null;
    onCreateEffect() {
        // ensure the effect tonemapping value is initialized
        if (this.mode.isInitialized == false) {
            const mode = threeToNeedleToneMapping(this.context.renderer.toneMapping);
            if (debug)
                console.log("[PostProcessing] Initializing ToneMapping mode to renderer.toneMapping", this.context.renderer.toneMapping + " → " + mode);
            this.mode.initialize(mode);
        }
        this._tonemappingEffect?.dispose();
        const threeMode = toThreeToneMapping(this.mode.value);
        const tonemapping = this._tonemappingEffect = new MODULES.POSTPROCESSING.MODULE.ToneMappingEffect({
            mode: threeToneMappingToEffectMode(threeMode),
        });
        this.mode.onValueChanged = (newValue) => {
            if (typeof newValue === "string") {
                newValue = nameToThreeTonemapping(newValue);
                tonemapping.mode = threeToneMappingToEffectMode(newValue);
            }
            else {
                const threeMode = toThreeToneMapping(newValue);
                tonemapping.mode = threeToneMappingToEffectMode(threeMode);
            }
            tonemapping.name = "ToneMapping (" + NEToneMappingMode[newValue] + ")";
            if (debug)
                console.log("[PostProcessing] ToneMapping mode changed to", NEToneMappingMode[newValue], threeMode, tonemapping.mode);
        };
        if (debug)
            console.log("[PostProcessing] Use ToneMapping", NEToneMappingMode[this.mode.value], threeMode, tonemapping.mode, "renderer.tonemapping: " + this.context.renderer.toneMapping);
        return tonemapping;
    }
    onBeforeRender() {
        if (this._tonemappingEffect && this.postprocessingContext?.handler.getEffectIsActive(this._tonemappingEffect)) {
            if (this.mode.overrideState)
                this.context.renderer.toneMapping = toThreeToneMapping(this.mode.value);
            if (this.exposure.overrideState && this.exposure.value !== undefined) {
                const newValue = Math.max(0.0, this.exposure.value);
                this.context.renderer.toneMappingExposure = newValue;
            }
        }
    }
}
__decorate([
    serializable(VolumeParameter)
], ToneMappingEffect.prototype, "mode", void 0);
__decorate([
    serializable(VolumeParameter)
], ToneMappingEffect.prototype, "exposure", void 0);
registerCustomEffectType("Tonemapping", ToneMappingEffect);
//# sourceMappingURL=Tonemapping.js.map