import { Disposable, ObservableVector4, DRef, Vector3 } from '@zephyr3d/base';
import '../values.js';
import '../render/render_queue.js';
import '../render/primitive.js';
import '@zephyr3d/device';
import '../material/shader/helper.js';
import '../material/lambert.js';
import '../material/blinn.js';
import '../material/unlit.js';
import '../material/particle.js';
import '../material/meshmaterial.js';
import '../material/grassmaterial.js';
import '../material/terrain-cm.js';
import '../material/pbrmr.js';
import '../material/pbrsg.js';
import '../material/pbrblueprint.js';
import '../material/sprite.js';
import '../material/sprite_std.js';
import '../utility/blueprint/material/texture.js';
import '../render/rendergraph/forward_plus_builder.js';
import { SkyRenderer } from '../render/sky.js';
import '../render/clipmap.js';
import { EnvShIBL, EnvHemisphericAmbient, EnvConstantAmbient } from '../render/envlight.js';
import '../shaders/atmosphere.js';

/**
 * Wrapper for environmant lighting
 * @public
 */ class EnvLightWrapper extends Disposable {
    _envLight;
    _ambientColor;
    _ambientDown;
    _ambientUp;
    _radianceMap;
    _irradianceMap;
    _irradianceSH;
    _irradianceSHFB;
    _irradianceWindow;
    _strength;
    /** @internal */ constructor(){
        super();
        this._envLight = new EnvShIBL();
        this._ambientColor = new ObservableVector4(0.2, 0.2, 0.2, 1).setCallback(()=>{
            if (this.type === 'constant') {
                this._envLight.ambientColor.set(this._ambientColor);
            }
        });
        this._ambientDown = new ObservableVector4(0.2, 0.2, 0.2, 1).setCallback(()=>{
            if (this.type === 'hemisphere') {
                this._envLight.ambientDown.set(this._ambientDown);
            }
        });
        this._ambientUp = new ObservableVector4(0.3, 0.5, 0.8, 1).setCallback(()=>{
            if (this.type === 'hemisphere') {
                this._envLight.ambientUp.set(this._ambientUp);
            }
        });
        this._radianceMap = new DRef();
        this._irradianceMap = new DRef();
        this._irradianceSH = new DRef();
        this._irradianceSHFB = new DRef();
        this._irradianceWindow = new Vector3();
        this._strength = 1;
    }
    /** @internal */ getHash(ctx) {
        const irradianceSource = this.type === 'ibl' ? this._irradianceSHFB.get() ? 'fb' : this._irradianceSH.get() ? 'buf' : 'none' : 'na';
        return !ctx || ctx.drawEnvLight ? `${this.type}:${this._envLight.hasRadiance() ? '1' : '0'}:${this._envLight.hasIrradiance() ? '1' : '0'}:${irradianceSource}` : 'none';
    }
    /** @internal */ get envLight() {
        return this._envLight;
    }
    /** The strength of environment lighting */ get strength() {
        return this._strength;
    }
    set strength(val) {
        this._strength = val;
    }
    /** Ambient light color for environment light type constant */ get ambientColor() {
        return this._ambientColor;
    }
    set ambientColor(val) {
        this._ambientColor.set(val);
    }
    /** Up color for environment light type hemisphere */ get ambientUp() {
        return this._ambientUp;
    }
    set ambientUp(val) {
        this._ambientUp.set(val);
    }
    /** Down color for environment light type hemisphere */ get ambientDown() {
        return this._ambientDown;
    }
    set ambientDown(val) {
        this._ambientDown.set(val);
    }
    /** Radiance map for environment light type ibl */ get radianceMap() {
        return this._radianceMap.get();
    }
    set radianceMap(tex) {
        this._radianceMap.set(tex);
        if (this.type === 'ibl') {
            this._envLight.radianceMap = this.radianceMap;
        }
    }
    /** Irradiance SH buffer for environment light type ibl */ get irradianceSH() {
        return this._irradianceSH.get();
    }
    set irradianceSH(value) {
        this._irradianceSH.set(value);
        if (this.type === 'ibl') {
            this._envLight.irradianceSH = this.irradianceSH;
        }
    }
    /** Irradiance SH texture for environment light type ibl */ get irradianceSHFB() {
        return this._irradianceSHFB.get();
    }
    set irradianceSHFB(value) {
        this._irradianceSHFB.set(value);
        if (this.type === 'ibl') {
            this._envLight.irradianceSHFB = this.irradianceSHFB;
        }
    }
    /** Irradiance SH window for environment light type ibl */ get irradianceWindow() {
        return this._irradianceWindow;
    }
    set irradianceWindow(value) {
        this._irradianceWindow.set(value);
        if (this.type === 'ibl') {
            this._envLight.irradianceWindow = this._irradianceWindow;
        }
    }
    /** The environment light type */ get type() {
        return this._envLight?.getType() ?? 'none';
    }
    set type(val) {
        switch(val){
            case 'none':
                this._envLight = null;
                break;
            case 'ibl':
                if (this._envLight?.getType() !== val) {
                    this._envLight = new EnvShIBL(this.radianceMap, this.irradianceSH, this.irradianceSHFB);
                }
                this._envLight.radianceMap = this.radianceMap;
                this._envLight.irradianceSH = this.irradianceSH;
                this._envLight.irradianceSHFB = this.irradianceSHFB;
                this._envLight.irradianceWindow = this.irradianceWindow;
                break;
            case 'constant':
                if (this._envLight?.getType() !== val) {
                    this._envLight = new EnvConstantAmbient(this._ambientColor);
                }
                break;
            case 'hemisphere':
                if (this._envLight?.getType() !== val) {
                    this._envLight = new EnvHemisphericAmbient(this._ambientUp, this._ambientDown);
                }
                break;
        }
    }
    /** Disposes the environment lighting wrapper */ onDispose() {
        super.onDispose();
        this._envLight?.dispose();
        this._radianceMap.dispose();
        this._irradianceMap.dispose();
        this._irradianceSHFB.dispose();
        this._irradianceSH.dispose();
    }
}
/**
 * Environment of scene
 * @public
 */ class Environment extends Disposable {
    _sky;
    _light;
    /** @internal */ constructor(){
        super();
        this._sky = new SkyRenderer();
        this._light = new EnvLightWrapper();
    }
    /** The sky renderer */ get sky() {
        return this._sky;
    }
    /** The environment lighting renderer */ get light() {
        return this._light;
    }
    /** @internal */ getHash(ctx) {
        return `${this.light?.getHash(ctx)}:${this._sky?.getHash(ctx)}`;
    }
    /** @internal */ needSceneDepthTexture() {
        return this._sky.fogType !== 'none';
    }
    /** Disposes the environment object */ onDispose() {
        super.onDispose();
        this._sky.dispose();
        this._light.dispose();
    }
}

export { EnvLightWrapper, Environment };
//# sourceMappingURL=environment.js.map
