/*---------------------------------------------------------------------------------------------
* 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 { JsonUtils } from "@itwin/core-bentley";
import { ColorDef } from "./ColorDef";
import { LinePixels } from "./LinePixels";
/** Namespace containing types controlling how edges and surfaces should be drawn in "hidden line" and "solid fill" [[RenderMode]]s.
 * @public
 */
export var HiddenLine;
(function (HiddenLine) {
    /** Describes the symbology with which edges should be drawn. */
    class Style {
        get ovrColor() { return undefined !== this.color; }
        /** If defined, the color used to draw the edges. If undefined, edges are drawn using the element's line color. */
        color;
        /** If defined, the pixel pattern used to draw the edges. If undefined, edges are drawn using the element's line pattern. */
        pattern;
        /** If defined, the width of the edges in pixels. If undefined (or 0), edges are drawn using the element's line width.
         * @note Non-integer values are truncated, and values are clamped to the range [1, 32].
         */
        width;
        constructor(json, hidden) {
            if (JsonUtils.isEmptyObjectOrUndefined(json)) {
                if (hidden)
                    this.pattern = LinePixels.HiddenLine;
                return;
            }
            json = json; // per JsonUtils.isEmptyObjectOrUndefined()
            if (undefined !== json.color && false !== json.ovrColor)
                this.color = ColorDef.fromJSON(json.color);
            if (undefined !== json.pattern) {
                const pattern = JsonUtils.asInt(json.pattern, hidden ? LinePixels.HiddenLine : LinePixels.Invalid);
                if (LinePixels.Invalid !== pattern)
                    this.pattern = pattern;
            }
            else if (hidden) {
                this.pattern = LinePixels.HiddenLine;
            }
            if (undefined !== json.width) {
                let width = JsonUtils.asInt(json.width, 0);
                if (0 !== width) {
                    width = Math.max(1, width);
                    this.width = Math.min(32, width);
                }
            }
        }
        static defaultVisible = new Style({});
        static defaultHidden = new Style({}, true);
        static fromJSON(json, hidden) {
            if (undefined !== json)
                return new Style(json, hidden);
            return hidden ? this.defaultHidden : this.defaultVisible;
        }
        /** Create a Style equivalent to this one but with the specified color override. */
        overrideColor(color) {
            if (undefined === this.color && undefined === color)
                return this;
            if (undefined !== this.color && undefined !== color && this.color.equals(color))
                return this;
            return Style.fromJSON({
                color: color?.toJSON(),
                ovrColor: undefined !== color,
                pattern: this.pattern,
                width: this.width,
            });
        }
        /** Create a Style equivalent to this one but with the specified pattern override. */
        overridePattern(pattern) {
            if (pattern === this.pattern)
                return this;
            return Style.fromJSON({
                color: this.color?.toJSON(),
                ovrColor: this.ovrColor,
                pattern,
                width: this.width,
            });
        }
        /** Create a Style equivalent to this one but with the specified width override. */
        overrideWidth(width) {
            if (width === this.width)
                return this;
            return Style.fromJSON({
                color: this.color?.toJSON(),
                ovrColor: this.ovrColor,
                pattern: this.pattern,
                width,
            });
        }
        /** Returns true if this Style is equivalent to the supplied Style. */
        equals(other) {
            if (this === other)
                return true;
            else if (this.ovrColor !== other.ovrColor || this.pattern !== other.pattern || this.width !== other.width)
                return false;
            else if ((undefined === this.color) !== (undefined === other.color))
                return false;
            else
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                return undefined === this.color || this.color.equals(other.color);
        }
        toJSON() {
            return {
                ovrColor: this.ovrColor,
                color: this.color ? this.color.toJSON() : ColorDef.white.toJSON(),
                pattern: undefined !== this.pattern ? this.pattern : LinePixels.Invalid,
                width: undefined !== this.width ? this.width : 0,
            };
        }
    }
    HiddenLine.Style = Style;
    /** Describes how visible and hidden edges and transparent surfaces should be rendered in "hidden line" and "solid fill" [[RenderMode]]s. */
    class Settings {
        /** Describes how visible edges (those unobscured by other geometry) should be displayed. */
        visible;
        /** Describes how hidden edges (those obscured by other geometry) should be displayed. */
        hidden;
        /** A value in the range [0.0, 1.0] specifying a threshold below which transparent surfaces should not be drawn.
         * A value of 0.0 indicates any surface that is not 100% opaque should not be drawn.
         * A value of 0.25 indicates any surface that is less than 25% opaque should not be drawn.
         * A value of 1.0 indicates that all surfaces should be drawn regardless of transparency.
         * @note values will be clamped to the range [0.0, 1.0].
         * @note Defaults to 1.0.
         */
        transparencyThreshold;
        /** An alias for [[transparencyThreshold]]. */
        get transThreshold() { return this.transparencyThreshold; }
        /** The default display settings. */
        static defaults = new Settings({});
        /** Create a DisplaySettings from its JSON representation. */
        static fromJSON(json) {
            if (!JsonUtils.isNonEmptyObject(json))
                return this.defaults;
            else if (json instanceof Settings)
                return json;
            else
                return new Settings(json);
        }
        toJSON() {
            const props = {
                visible: this.visible.toJSON(),
                hidden: this.hidden.toJSON(),
                transThreshold: this.transThreshold,
            };
            return props;
        }
        /** Create a Settings equivalent to this one with the exception of those properties defined in the supplied JSON. */
        override(props) {
            const visible = props.visible;
            const hidden = props.hidden;
            const transparencyThreshold = props.transThreshold;
            return Settings.fromJSON({
                visible: undefined !== visible ? visible : this.visible.toJSON(),
                hidden: undefined !== hidden ? hidden : this.hidden.toJSON(),
                transThreshold: undefined !== transparencyThreshold ? transparencyThreshold : this.transparencyThreshold,
            });
        }
        equals(other) {
            if (this === other)
                return true;
            return this.visible.equals(other.visible)
                && this.hidden.equals(other.hidden)
                && this.transparencyThreshold === other.transparencyThreshold;
        }
        get matchesDefaults() {
            return this.equals(Settings.defaults);
        }
        constructor(json) {
            this.visible = Style.fromJSON(json.visible);
            this.hidden = Style.fromJSON(json.hidden, true);
            this.transparencyThreshold = JsonUtils.asDouble(json.transThreshold, 1.0);
        }
    }
    HiddenLine.Settings = Settings;
})(HiddenLine || (HiddenLine = {}));
//# sourceMappingURL=HiddenLine.js.map