"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 IModelComponents
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelsTree = exports.RULESET_MODELS_GROUPED_BY_CLASS = exports.RULESET_MODELS = void 0;
/* eslint-disable deprecation/deprecation */
require("./ModelsTree.scss");
const React = require("react");
const components_react_1 = require("@itwin/components-react");
const core_react_1 = require("@itwin/core-react");
const presentation_components_1 = require("@itwin/presentation-components");
const presentation_frontend_1 = require("@itwin/presentation-frontend");
const UiFramework_1 = require("../../../appui-react/UiFramework");
const Common_1 = require("../Common");
const VisibilityTreeEventHandler_1 = require("../VisibilityTreeEventHandler");
const VisibilityTreeRenderer_1 = require("../VisibilityTreeRenderer");
const ModelsVisibilityHandler_1 = require("./ModelsVisibilityHandler");
const PAGING_SIZE = 20;
/** @internal */
exports.RULESET_MODELS = require("./Hierarchy.json"); // eslint-disable-line @typescript-eslint/no-var-requires
/** @internal */
exports.RULESET_MODELS_GROUPED_BY_CLASS = require("./Hierarchy.GroupedByClass.json"); // eslint-disable-line @typescript-eslint/no-var-requires
const RULESET_MODELS_SEARCH = require("./ModelsTreeSearch.json"); // eslint-disable-line @typescript-eslint/no-var-requires
/**
 * A tree component that shows a subject - model - category - element
 * hierarchy along with checkboxes that represent and allow changing
 * the display of those instances.
 * @public
 * @deprecated in 3.6. Was moved to `@itwin/tree-widget-react` package.
 */
function ModelsTree(props) {
    const { nodeLoader, onItemsRendered } = useModelsTreeNodeLoader(props);
    const { filteredNodeLoader, isFiltering, nodeHighlightingProps } = (0, VisibilityTreeRenderer_1.useVisibilityTreeFiltering)(nodeLoader, props.filterInfo, props.onFilterApplied);
    const filterApplied = filteredNodeLoader !== nodeLoader;
    const { activeView, modelsVisibilityHandler, selectionPredicate } = props;
    const nodeSelectionPredicate = React.useCallback((key, node) => {
        return !selectionPredicate ? true : selectionPredicate(key, ModelsVisibilityHandler_1.ModelsVisibilityHandler.getNodeType(node, nodeLoader.dataProvider));
    }, [selectionPredicate, nodeLoader.dataProvider]);
    const visibilityHandler = useVisibilityHandler(nodeLoader.dataProvider.rulesetId, props.iModel, activeView, modelsVisibilityHandler, getFilteredDataProvider(filteredNodeLoader.dataProvider), props.enableHierarchyAutoUpdate);
    const eventHandler = (0, core_react_1.useDisposable)(React.useCallback(() => new VisibilityTreeEventHandler_1.VisibilityTreeEventHandler({
        nodeLoader: filteredNodeLoader,
        visibilityHandler,
        collapsedChildrenDisposalEnabled: true,
        selectionPredicate: nodeSelectionPredicate,
    }), [filteredNodeLoader, visibilityHandler, nodeSelectionPredicate]));
    const treeModel = (0, components_react_1.useTreeModel)(filteredNodeLoader.modelSource);
    const treeRenderer = (0, VisibilityTreeRenderer_1.useVisibilityTreeRenderer)(true, false);
    const overlay = isFiltering ? React.createElement("div", { className: "filteredTreeOverlay" }) : undefined;
    // istanbul ignore next
    const noFilteredDataRenderer = React.useCallback(() => {
        return React.createElement(VisibilityTreeRenderer_1.VisibilityTreeNoFilteredData, { title: UiFramework_1.UiFramework.localization.getLocalizedString("UiFramework:modelTree.noModelFound"), message: UiFramework_1.UiFramework.localization.getLocalizedString("UiFramework:modelTree.noMatchingModelNames") });
    }, []);
    return (React.createElement("div", { className: "ui-fw-models-tree", ref: props.rootElementRef },
        React.createElement(components_react_1.ControlledTree, { nodeLoader: filteredNodeLoader, model: treeModel, selectionMode: props.selectionMode || components_react_1.SelectionMode.None, eventsHandler: eventHandler, treeRenderer: treeRenderer, nodeHighlightingProps: nodeHighlightingProps, noDataRenderer: filterApplied ? noFilteredDataRenderer : undefined, onItemsRendered: onItemsRendered, width: props.width, height: props.height }),
        overlay));
}
exports.ModelsTree = ModelsTree;
function useModelsTreeNodeLoader(props) {
    var _a, _b;
    // note: this is a temporary workaround for auto-update not working on ruleset variable changes - instead
    // of auto-updating we just re-create the node loader by re-creating the ruleset
    const rulesets = React.useMemo(() => {
        return {
            general: (!props.enableElementsClassGrouping) ? { ...exports.RULESET_MODELS } : /* istanbul ignore next */ { ...exports.RULESET_MODELS_GROUPED_BY_CLASS },
            search: { ...RULESET_MODELS_SEARCH },
        };
    }, [props.filteredElementIds]); // eslint-disable-line react-hooks/exhaustive-deps
    // const rulesets = {
    //   general: (!props.enableElementsClassGrouping) ? RULESET_MODELS : /* istanbul ignore next */ RULESET_MODELS_GROUPED_BY_CLASS,
    //   search: RULESET_MODELS_SEARCH,
    // };
    const { nodeLoader, onItemsRendered } = (0, presentation_components_1.usePresentationTreeNodeLoader)({
        imodel: props.iModel,
        ruleset: rulesets.general,
        appendChildrenCountForGroupingNodes: (props.enableElementsClassGrouping === Common_1.ClassGroupingOption.YesWithCounts),
        pagingSize: PAGING_SIZE,
        enableHierarchyAutoUpdate: props.enableHierarchyAutoUpdate,
    });
    const { nodeLoader: searchNodeLoader, onItemsRendered: onSearchItemsRendered } = (0, presentation_components_1.usePresentationTreeNodeLoader)({
        imodel: props.iModel,
        ruleset: rulesets.search,
        pagingSize: PAGING_SIZE,
        enableHierarchyAutoUpdate: props.enableHierarchyAutoUpdate,
    });
    const activeNodeLoader = ((_a = props.filterInfo) === null || _a === void 0 ? void 0 : _a.filter) ? searchNodeLoader : nodeLoader;
    const activeItemsRenderedCallback = ((_b = props.filterInfo) === null || _b === void 0 ? void 0 : _b.filter) ? onSearchItemsRendered : onItemsRendered;
    const vars = presentation_frontend_1.Presentation.presentation.vars(activeNodeLoader.dataProvider.rulesetId);
    if (props.filteredElementIds) {
        // eslint-disable-next-line @typescript-eslint/no-floating-promises
        vars.setId64s("filtered-element-ids", props.filteredElementIds);
    }
    else {
        // eslint-disable-next-line @typescript-eslint/no-floating-promises
        vars.unset("filtered-element-ids");
    }
    return {
        nodeLoader: activeNodeLoader,
        onItemsRendered: activeItemsRenderedCallback,
    };
}
function useVisibilityHandler(rulesetId, iModel, activeView, visibilityHandler, filteredDataProvider, hierarchyAutoUpdateEnabled) {
    const subjectModelIdsCache = React.useMemo(() => new ModelsVisibilityHandler_1.SubjectModelIdsCache(iModel), [iModel]);
    const defaultVisibilityHandler = (0, core_react_1.useOptionalDisposable)(React.useCallback(() => {
        if (activeView)
            return createVisibilityHandler(rulesetId, activeView, subjectModelIdsCache, hierarchyAutoUpdateEnabled);
        return undefined;
    }, [rulesetId, activeView, subjectModelIdsCache, hierarchyAutoUpdateEnabled]));
    const handler = visibilityHandler !== null && visibilityHandler !== void 0 ? visibilityHandler : defaultVisibilityHandler;
    React.useEffect(() => {
        handler && handler.setFilteredDataProvider(filteredDataProvider);
    }, [handler, filteredDataProvider]);
    return handler;
}
const createVisibilityHandler = (rulesetId, activeView, subjectModelIdsCache, hierarchyAutoUpdateEnabled) => {
    // istanbul ignore next
    return new ModelsVisibilityHandler_1.ModelsVisibilityHandler({ rulesetId, viewport: activeView, hierarchyAutoUpdateEnabled, subjectModelIdsCache });
};
const isFilteredDataProvider = (dataProvider) => {
    const filteredProvider = dataProvider;
    return filteredProvider.nodeMatchesFilter !== undefined && filteredProvider.getActiveMatch !== undefined && filteredProvider.countFilteringResults !== undefined;
};
const getFilteredDataProvider = (dataProvider) => {
    return isFilteredDataProvider(dataProvider) ? dataProvider : undefined;
};
//# sourceMappingURL=ModelsTree.js.map