"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Views
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlanarClipMaskState = void 0;
const core_common_1 = require("@itwin/core-common");
const FeatureSymbology_1 = require("./render/FeatureSymbology");
const core_geometry_1 = require("@itwin/core-geometry");
/** The State of Planar Clip Mask applied to a reality model or background map.
 * Handles loading models and their associated tiles for models that are used by masks but may not be otherwise loaded or displayed.
 * @beta
 */
class PlanarClipMaskState {
    constructor(settings) {
        this._allLoaded = false;
        this._usingViewportOverrides = false;
        this._maskRange = core_geometry_1.Range3d.createNull();
        this.settings = settings;
    }
    static create(settings) {
        return new PlanarClipMaskState(settings);
    }
    static fromJSON(props) {
        return this.create(core_common_1.PlanarClipMaskSettings.fromJSON(props));
    }
    get usingViewportOverrides() { return this._usingViewportOverrides; }
    ;
    discloseTileTrees(trees) {
        if (this._tileTreeRefs)
            this._tileTreeRefs.forEach((treeRef) => treeRef.discloseTileTrees(trees));
    }
    // Returns the TileTreeReferences for the models that need to be drawn to create the planar clip mask, and extend the maskRange if needed.
    getTileTrees(view, classifiedModelId, maskRange) {
        if (this.settings.mode === core_common_1.PlanarClipMaskMode.Priority) {
            // For priority mode we simply want refs for all viewed models if the priority is higher than the mask priority.
            // For this case, we don't need a maskRange so leave it as null.
            const viewTrees = new Array();
            const thisPriority = this.settings.priority === undefined ? core_common_1.PlanarClipMaskPriority.RealityModel : this.settings.priority;
            view.forEachTileTreeRef((ref) => {
                const tree = ref.treeOwner.load();
                if (tree && tree.modelId !== classifiedModelId && ref.planarclipMaskPriority > thisPriority)
                    viewTrees.push(ref);
            });
            return viewTrees;
        }
        // For all other modes we need to let the tree refs in the view state decide which refs need to be drawn
        // since batched tiles cannot turn on/off individual models just by their tile tree refs.
        // Keep calling this until loaded so that the range is valid.
        if (!this._allLoaded) {
            this._tileTreeRefs = new Array();
            if (this.settings.modelIds) {
                view.collectMaskRefs(this.settings.modelIds, this._tileTreeRefs, maskRange);
            }
            this._allLoaded = this._tileTreeRefs.every((treeRef) => treeRef.treeOwner.load() !== undefined);
            maskRange.clone(this._maskRange);
        }
        else // If already loaded, just set the maskRange to the saved maskRange.
            this._maskRange.clone(maskRange);
        return this._allLoaded ? this._tileTreeRefs : undefined;
    }
    // Returns any potential FeatureSymbology overrides for drawing the planar clip mask.
    getPlanarClipMaskSymbologyOverrides(view, context, featureSymbologySource) {
        this._usingViewportOverrides = false;
        // First obtain a list of models that will need to be turned off for drawing the planar clip mask (only used for batched tile trees).
        const overrideModels = view.getModelsNotInMask(this.settings.modelIds, core_common_1.PlanarClipMaskMode.Priority === this.settings.mode);
        const noSubCategoryOrElementIds = !this.settings.subCategoryOrElementIds;
        if (noSubCategoryOrElementIds && !overrideModels)
            return undefined;
        const ovrBasedOnContext = core_common_1.PlanarClipMaskMode.Priority === this.settings.mode || core_common_1.PlanarClipMaskMode.Models === this.settings.mode || noSubCategoryOrElementIds;
        const viewport = overrideModels && ovrBasedOnContext ? context.viewport : undefined;
        const overrides = FeatureSymbology_1.FeatureSymbology.Overrides.withSource(featureSymbologySource, viewport);
        if (overrideModels) {
            // overrideModels is used for batched models.  For those, we need to create model overrides to turn off models that are
            // not wanted in the mask (using transparency) no matter what mask mode is being used.
            const appOff = core_common_1.FeatureAppearance.fromTransparency(1.0);
            // For Priority or Models mode, we need to start with the current overrides and modify them
            if (ovrBasedOnContext) {
                this._usingViewportOverrides = true; // Set flag to use listener since context.viewport might change afterwards.
                overrides.addInvisibleElementOverridesToNeverDrawn(); // need this for fully trans element overrides to not participate in mask
                overrideModels.forEach((modelId) => {
                    overrides.override({ modelId, appearance: appOff, onConflict: "replace" });
                });
                return overrides;
            }
            // Otherwise, we just start with a default overrides and modify it.
            overrideModels.forEach((modelId) => {
                overrides.override({ modelId, appearance: appOff, onConflict: "replace" });
            });
        }
        // Add overrides to turn things on or off based on the subcategories or elements in the mask settings.
        switch (this.settings.mode) {
            case core_common_1.PlanarClipMaskMode.IncludeElements: {
                overrides.setAlwaysDrawnSet(this.settings.subCategoryOrElementIds, true);
                return overrides;
            }
            case core_common_1.PlanarClipMaskMode.ExcludeElements: {
                overrides.ignoreSubCategory = true;
                overrides.setNeverDrawnSet(this.settings.subCategoryOrElementIds);
                return overrides;
            }
            case core_common_1.PlanarClipMaskMode.IncludeSubCategories: {
                for (const subCategoryId of this.settings.subCategoryOrElementIds)
                    overrides.setVisibleSubCategory(subCategoryId);
                return overrides;
            }
        }
        return undefined;
    }
}
exports.PlanarClipMaskState = PlanarClipMaskState;
//# sourceMappingURL=PlanarClipMaskState.js.map