/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module DisplayStyles
 */
import { Id64 } from "@itwin/core-bentley";
import { ColorDef } from "./ColorDef";
/** Supported types of [[SkyBox]] images.
 * @see [[SkyBoxImageProps]].
 * @public
 * @extensions
 */
export var SkyBoxImageType;
(function (SkyBoxImageType) {
    /** No image, indicating a [[SkyGradient]] should be displayed. */
    SkyBoxImageType[SkyBoxImageType["None"] = 0] = "None";
    /** A single image mapped to the surface of a sphere.
     * @see [[SkySphere]].
     */
    SkyBoxImageType[SkyBoxImageType["Spherical"] = 1] = "Spherical";
    /** @internal not yet supported */
    SkyBoxImageType[SkyBoxImageType["Cylindrical"] = 2] = "Cylindrical";
    /** Six images mapped to the faces of a cube.
     * @see [[SkyCube]].
     */
    SkyBoxImageType[SkyBoxImageType["Cube"] = 3] = "Cube";
})(SkyBoxImageType || (SkyBoxImageType = {}));
const defaultGroundColor = ColorDef.from(143, 205, 125);
const defaultZenithColor = ColorDef.from(54, 117, 255);
const defaultNadirColor = ColorDef.from(40, 125, 0);
const defaultSkyColor = ColorDef.from(142, 205, 255);
const defaultExponent = 4.0;
function colorDefFromJson(props) {
    return undefined !== props ? ColorDef.fromJSON(props) : undefined;
}
/** Describes how to map a two- or four-color [[Gradient]] to the interior of a sphere to produce a [[SkyBox]].
 * @see [[SkyBox.gradient]].
 * @public
 */
export class SkyGradient {
    twoColor;
    skyColor;
    groundColor;
    zenithColor;
    nadirColor;
    skyExponent;
    groundExponent;
    constructor(args) {
        this.twoColor = args.twoColor ?? false;
        this.skyColor = args.skyColor ?? defaultSkyColor;
        this.groundColor = args.groundColor ?? defaultGroundColor;
        this.nadirColor = args.nadirColor ?? defaultNadirColor;
        this.zenithColor = args.zenithColor ?? defaultZenithColor;
        this.skyExponent = args.skyExponent ?? defaultExponent;
        this.groundExponent = args.groundExponent ?? defaultExponent;
    }
    /** Default settings for a four-color gradient. */
    static defaults = new SkyGradient({});
    /** Create a new gradient. Any properties not specified by `props` are initialized to their default values. */
    static create(props) {
        return props ? new this(props) : this.defaults;
    }
    /** Create from JSON representation. */
    static fromJSON(props) {
        if (!props)
            return this.defaults;
        return new this({
            twoColor: props.twoColor,
            skyExponent: props.skyExponent,
            groundExponent: props.groundExponent,
            skyColor: colorDefFromJson(props.skyColor),
            groundColor: colorDefFromJson(props.groundColor),
            nadirColor: colorDefFromJson(props.nadirColor),
            zenithColor: colorDefFromJson(props.zenithColor),
        });
    }
    /** Create ea copy of this gradient, identical except for any properties explicitly specified by `changedProps`.
     * Any properties of `changedProps` explicitly set to `undefined` will be reset to their default values.
     */
    clone(changedProps) {
        return new SkyGradient({ ...this, ...changedProps });
    }
    /** Convert to JSON representation. */
    toJSON() {
        const props = {
            skyColor: this.skyColor.toJSON(),
            groundColor: this.groundColor.toJSON(),
            nadirColor: this.nadirColor.toJSON(),
            zenithColor: this.zenithColor.toJSON(),
        };
        if (this.groundExponent !== defaultExponent)
            props.groundExponent = this.groundExponent;
        if (this.skyExponent !== defaultExponent)
            props.skyExponent = this.skyExponent;
        if (this.twoColor)
            props.twoColor = this.twoColor;
        return props;
    }
    /** Returns true if this gradient is equivalent to the supplied gradient. */
    equals(other) {
        if (this === other)
            return true;
        return this.twoColor === other.twoColor && this.skyColor.equals(other.skyColor) && this.groundColor.equals(other.groundColor) &&
            this.zenithColor.equals(other.zenithColor) && this.nadirColor.equals(other.nadirColor);
    }
}
/** Describes how to draw a representation of a sky, as part of an [[Environment]].
 * @see [[SkyBoxProps]].
 * @public
 */
export class SkyBox {
    /** The gradient settings, used if no cube or sphere images are supplied, or if the images cannot be loaded. */
    gradient;
    constructor(gradient) {
        this.gradient = gradient;
    }
    /** Default settings for a four-color gradient. */
    static defaults = new SkyBox(SkyGradient.defaults);
    /** Create a skybox that displays the specified gradient, or the default gradient if none is supplied. */
    static createGradient(gradient) {
        return gradient ? new this(gradient) : this.defaults;
    }
    /** Create from JSON representation. */
    static fromJSON(props) {
        const gradient = SkyGradient.fromJSON(props);
        if (props?.image) {
            switch (props.image.type) {
                case SkyBoxImageType.Spherical:
                    if (undefined !== props.image.texture)
                        return new SkySphere(props.image.texture, gradient);
                    break;
                case SkyBoxImageType.Cube: {
                    const tx = props.image.textures;
                    if (tx && undefined !== tx.top && undefined !== tx.bottom && undefined !== tx.right && undefined !== tx.left && undefined !== tx.front && undefined !== tx.back)
                        return new SkyCube(tx, gradient);
                    break;
                }
            }
        }
        return this.createGradient(gradient);
    }
    /** Convert to JSON representation.
     * @param display If defined, the value to use for [[SkyBoxProps.display]]; otherwise, that property will be left undefined.
     */
    toJSON(display) {
        const props = this.gradient.toJSON();
        if (undefined !== display)
            props.display = display;
        return props;
    }
    /** @internal */
    get textureIds() {
        return [];
    }
}
/** Describes how to draw a representation of a sky by mapping a single image to the interior of a sphere.
 * @public
 */
export class SkySphere extends SkyBox {
    /** The image to map to the interior of the sphere. */
    image;
    /** Create a new sky sphere using the specified image.
     * @param image The image to map to the interior of the sphere.
     * @param gradient Optionally overrides the default gradient settings used if the image cannot be obtained.
     */
    constructor(image, gradient) {
        super(gradient ?? SkyGradient.defaults);
        this.image = image;
    }
    /** See [[SkyBox.toJSON]]. */
    toJSON(display) {
        const props = super.toJSON(display);
        props.image = {
            type: SkyBoxImageType.Spherical,
            texture: this.image,
        };
        return props;
    }
    /** @internal */
    get textureIds() {
        return Id64.isValidId64(this.image) ? [this.image] : [];
    }
}
/** Describes how to draw a representation of a sky by mapping images to the interior faces of a cube.
 * The images are required to be *square*, and each image must have the same dimensions as the other images.
 * @public
 */
export class SkyCube extends SkyBox {
    /** The images to map to each face of the cube. */
    images;
    /** Create a new sky cube using the specified images.
     * @param images The images to map to each face of the cube.
     * @param gradient Optionally overrides  the default gradient settings used if the images cannot be obtained.
     */
    constructor(images, gradient) {
        super(gradient ?? SkyGradient.defaults);
        this.images = { ...images };
    }
    /** See [[SkyBox.toJSON]]. */
    toJSON(display) {
        const props = super.toJSON(display);
        props.image = {
            type: SkyBoxImageType.Cube,
            textures: { ...this.images },
        };
        return props;
    }
    /** @internal */
    get textureIds() {
        const imgs = this.images;
        return [imgs.front, imgs.back, imgs.top, imgs.bottom, imgs.left, imgs.right].filter((x) => Id64.isValidId64(x));
    }
}
//# sourceMappingURL=SkyBox.js.map