"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createClassifierTileTreeReference = exports.SpatialClassifierTileTreeReference = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Tiles
 */
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const IModelApp_1 = require("../IModelApp");
const ModelState_1 = require("../ModelState");
const internal_1 = require("./internal");
function compareIds(lhs, rhs) {
    return (0, core_bentley_1.compareNumbers)(lhs.type, rhs.type) || (0, core_bentley_1.compareNumbers)(lhs.expansion, rhs.expansion)
        || (0, core_bentley_1.compareStrings)(lhs.modelId, rhs.modelId) || (0, core_bentley_1.compareStringsOrUndefined)(lhs.animationId, rhs.animationId)
        || (0, core_bentley_1.comparePossiblyUndefined)((x, y) => x.compareTo(y), lhs.timeline, rhs.timeline);
}
class ClassifierTreeSupplier {
    constructor() {
        this._nonexistentTreeOwner = {
            tileTree: undefined,
            loadStatus: internal_1.TileTreeLoadStatus.NotFound,
            load: () => undefined,
            dispose: () => undefined,
            loadTree: async () => undefined,
            iModel: undefined,
        };
    }
    compareTileTreeIds(lhs, rhs) {
        return compareIds(lhs, rhs);
    }
    async createTileTree(id, iModel) {
        await iModel.models.load(id.modelId);
        const model = iModel.models.getLoaded(id.modelId);
        if (undefined === model || !(model instanceof ModelState_1.GeometricModelState))
            return undefined;
        const idStr = (0, core_common_1.iModelTileTreeIdToString)(id.modelId, id, IModelApp_1.IModelApp.tileAdmin);
        const props = await IModelApp_1.IModelApp.tileAdmin.requestTileTreeProps(iModel, idStr);
        const params = (0, internal_1.iModelTileTreeParamsFromJSON)(props, iModel, id.modelId, {
            edges: false,
            allowInstancing: false,
            is3d: true,
            batchType: id.type,
            timeline: id.timeline,
        });
        return new internal_1.IModelTileTree(params, id);
    }
    getOwner(id, iModel) {
        return core_bentley_1.Id64.isValid(id.modelId) ? iModel.tiles.getTileTreeOwner(id, this) : this._nonexistentTreeOwner;
    }
    addModelsAnimatedByScript(modelIds, scriptSourceId, trees) {
        // Note: This is invoked when an element hosting a schedule script is updated - it doesn't care about frontend schedule scripts.
        for (const tree of trees)
            if (scriptSourceId === tree.id.animationId)
                modelIds.add(tree.id.modelId);
    }
    addSpatialModels(modelIds, trees) {
        for (const tree of trees)
            modelIds.add(tree.id.modelId);
    }
}
const classifierTreeSupplier = new ClassifierTreeSupplier();
/** @internal */
class SpatialClassifierTileTreeReference extends internal_1.TileTreeReference {
    get transparency() { return undefined; }
}
exports.SpatialClassifierTileTreeReference = SpatialClassifierTileTreeReference;
/** @internal */
class ClassifierTreeReference extends SpatialClassifierTileTreeReference {
    constructor(classifiers, classifiedTree, iModel, source) {
        super();
        this._id = createClassifierId(classifiers.active, source);
        this._source = source;
        this._iModel = iModel;
        this._classifiers = classifiers;
        this._classifiedTree = classifiedTree;
        this._owner = classifierTreeSupplier.getOwner(this._id, iModel);
    }
    get classifiers() { return this._classifiers; }
    get activeClassifier() { return this.classifiers.activeClassifier; }
    get castsShadows() {
        return false;
    }
    get treeOwner() {
        const newId = createClassifierId(this._classifiers.active, this._source);
        if (0 !== compareIds(this._id, newId)) {
            this._id = newId;
            this._owner = classifierTreeSupplier.getOwner(this._id, this._iModel);
        }
        return this.activeClassifier?.tileTreeReference?.treeOwner ?? this._owner;
    }
    discloseTileTrees(trees) {
        // NB: We do NOT call super because we don't use our tree if no classifier is active.
        trees.disclose(this._classifiedTree);
        const classifier = this.activeClassifier;
        const classifierTree = undefined !== classifier ? this.treeOwner.tileTree : undefined;
        if (undefined !== classifierTree)
            trees.add(classifierTree);
    }
    get isPlanar() {
        if (this.activeClassifier?.flags.isVolumeClassifier) {
            return false;
        }
        return true;
    }
    get viewFlags() {
        return {
            renderMode: core_common_1.RenderMode.SmoothShade,
            transparency: true, // Igored for point clouds as they don't support transparency.
            textures: false,
            lighting: false,
            shadows: false,
            monochrome: false,
            materials: false,
            ambientOcclusion: false,
            visibleEdges: false,
            hiddenEdges: false,
        };
    }
    // Add volume classifiers to scene (planar classifiers are added seperately.)
    addToScene(context) {
        if (this.isPlanar)
            return;
        const classifiedTree = this._classifiedTree.treeOwner.load();
        if (undefined === classifiedTree)
            return;
        const classifier = this._classifiers.activeClassifier;
        if (undefined === classifier)
            return;
        const classifierTree = this.treeOwner.load();
        if (undefined === classifierTree)
            return;
        context.setVolumeClassifier(classifier, classifiedTree.modelId);
        super.addToScene(context);
    }
}
/** @internal */
function createClassifierTileTreeReference(classifiers, classifiedTree, iModel, source) {
    return new ClassifierTreeReference(classifiers, classifiedTree, iModel, source);
}
exports.createClassifierTileTreeReference = createClassifierTileTreeReference;
function createClassifierId(classifier, source) {
    if (undefined === classifier)
        return { modelId: core_bentley_1.Id64.invalid, type: core_common_1.BatchType.PlanarClassifier, expansion: 0, animationId: undefined };
    const type = classifier.flags.isVolumeClassifier ? core_common_1.BatchType.VolumeClassifier : core_common_1.BatchType.PlanarClassifier;
    const scriptInfo = IModelApp_1.IModelApp.tileAdmin.getScriptInfoForTreeId(classifier.modelId, source?.scheduleScriptReference); // eslint-disable-line deprecation/deprecation
    return {
        modelId: classifier.modelId,
        type,
        expansion: classifier.expand,
        animationId: scriptInfo?.animationId,
        timeline: scriptInfo?.timeline,
    };
}
//# sourceMappingURL=ClassifierTileTree.js.map