/*---------------------------------------------------------------------------------------------
* 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 { Range1d } from "@itwin/core-geometry";
import { ThematicGradientSettings } from "./ThematicDisplay";
import { Gradient } from "./Gradient";
/** Describes how an [[AnalysisStyle]] deforms a [Polyface]($core-geometry) by applying translation to its vertices.
 * @see [[AnalysisStyle.displacement]].
 * @public
 */
export class AnalysisStyleDisplacement {
    /** The name of the [AuxChannel]($core-geometry) supplying the displacements to be applied to the vertices. */
    channelName;
    /** A scale applied to the displacements to adjust the magnitude of the effect.
     * Default value: 1.
     */
    scale;
    constructor(channelName, scale = 1) {
        this.channelName = channelName;
        this.scale = scale;
    }
    /** Create from JSON representation. */
    static fromJSON(props) {
        return new this(props.channelName, props.scale);
    }
    /** Convert to JSON representation. */
    toJSON() {
        const props = { channelName: this.channelName };
        if (this.scale !== 1)
            props.scale = this.scale;
        return props;
    }
    /** Return true if `this` is equivalent to `other`. */
    equals(other) {
        return this.channelName === other.channelName && this.scale === other.scale;
    }
}
/** Describes how an [[AnalysisStyle]] recolors [Polyface]($core-geometry) vertices by mapping values of type
 * [AuxChannelDataType.Scalar]($core-geometry) or [AuxChannelDataType.Distance]($core-geometry) supplied
 * by an [AuxChannel]($core-geometry) to colors supplied by a [[Gradient]] image.
 * @see [[AnalysisStyle.thematic]].
 * @public
 */
export class AnalysisStyleThematic {
    /** The name of the [AuxChannel]($core-geometry) supplying the values from which the vertex colors are computed. */
    channelName;
    /** The minimum and maximum values that map to colors in the [[Gradient]] image. Vertices with values outside of
     * this range are displayed with the gradient's margin color.
     */
    range;
    /** Settings used to produce the [[Gradient]] image. */
    thematicSettings;
    _gradient;
    constructor(props) {
        this.channelName = props.channelName;
        this.range = Range1d.fromJSON(props.range);
        this.thematicSettings = ThematicGradientSettings.fromJSON(props.thematicSettings);
    }
    /** Create from JSON representation. */
    static fromJSON(props) {
        return new this(props);
    }
    /** Convert to JSON representation. */
    toJSON() {
        const props = {
            channelName: this.channelName,
            range: this.range.toJSON(),
        };
        if (!this.thematicSettings.equals(ThematicGradientSettings.defaults))
            props.thematicSettings = this.thematicSettings.toJSON();
        return props;
    }
    /** The gradient computed from [[thematicSettings]]. */
    get gradient() {
        if (!this._gradient)
            this._gradient = Gradient.Symb.createThematic(this.thematicSettings);
        return this._gradient;
    }
    /** Return true if `this` is equivalent to `other`. */
    equals(other) {
        return this.channelName === other.channelName && this.range.isAlmostEqual(other.range) && this.thematicSettings.equals(other.thematicSettings);
    }
}
function tryConvertLegacyProps(input) {
    if (input.displacement || input.scalar)
        return input;
    const legacy = input;
    if (undefined === legacy.displacementChannelName && undefined === legacy.scalarChannelName)
        return input;
    const output = {
        normalChannelName: input.normalChannelName,
    };
    if (undefined !== legacy.displacementChannelName) {
        output.displacement = {
            channelName: legacy.displacementChannelName,
            scale: legacy.displacementScale,
        };
    }
    if (undefined !== legacy.scalarChannelName && undefined !== legacy.scalarRange) {
        output.scalar = {
            channelName: legacy.scalarChannelName,
            range: legacy.scalarRange,
            thematicSettings: legacy.scalarThematicSettings,
        };
    }
    return output;
}
/** As part of a [[DisplayStyleSettings]], describes how to animate meshes in the view that have been augmented with
 * [PolyfaceAuxData]($core-geometry). The style specifies which channels to use, and can deform the meshes by
 * translating vertices and/or recolor vertices using [[ThematicDisplay]].
 * @see [[DisplayStyleSettings.analysisStyle]] to define the analysis style for a [DisplayStyle]($backend).
 * @see [[DisplayStyleSettings.analysisFraction]] to control playback of the animation.
 * @public
 */
export class AnalysisStyle {
    displacement;
    thematic;
    /** If defined, the name of the [AuxChannel]($core-geometry) from which to obtain normal vectors for the vertices. */
    normalChannelName;
    /** Create an analysis style from its JSON representation.
     * @note AnalysisStyle is an immutable type - use [[clone]] to produce a modified copy.
     */
    static fromJSON(props) {
        if (!props)
            return this.defaults;
        props = tryConvertLegacyProps(props);
        if (!props.displacement && !props.scalar && undefined === props.normalChannelName)
            return this.defaults;
        return new AnalysisStyle(props);
    }
    constructor(props) {
        this.normalChannelName = props.normalChannelName;
        if (props.displacement)
            this.displacement = AnalysisStyleDisplacement.fromJSON(props.displacement);
        if (props.scalar)
            this.thematic = AnalysisStyleThematic.fromJSON(props.scalar);
    }
    /** Convert this style to its JSON representation. */
    toJSON() {
        const props = {};
        if (this === AnalysisStyle.defaults)
            return props;
        if (this.displacement)
            props.displacement = this.displacement.toJSON();
        if (this.thematic)
            props.scalar = this.thematic.toJSON();
        if (undefined !== this.normalChannelName)
            props.normalChannelName = this.normalChannelName;
        return props;
    }
    /** Produce a copy of this style identical except for properties explicitly specified by `changedProps`. */
    clone(changedProps) {
        return AnalysisStyle.fromJSON({
            ...this.toJSON(),
            ...changedProps,
        });
    }
    /** Return true if this style is equivalent to `other`. */
    equals(other) {
        if (this.normalChannelName !== other.normalChannelName)
            return false;
        if ((undefined === this.displacement) !== (undefined === other.displacement))
            return false;
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        else if (this.displacement && !this.displacement.equals(other.displacement))
            return false;
        if ((undefined === this.thematic) !== (undefined === other.thematic))
            return false;
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        return undefined === this.thematic || this.thematic.equals(other.thematic);
    }
    static defaults = new AnalysisStyle({});
}
//# sourceMappingURL=AnalysisStyle.js.map