/*---------------------------------------------------------------------------------------------
* 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
 */
/* eslint-disable deprecation/deprecation */
import "./ModelsTree.scss";
import * as React from "react";
import { ControlledTree, SelectionMode, useTreeModel } from "@itwin/components-react";
import { useDisposable, useOptionalDisposable } from "@itwin/core-react";
import { usePresentationTreeNodeLoader } from "@itwin/presentation-components";
import { Presentation } from "@itwin/presentation-frontend";
import { UiFramework } from "../../../appui-react/UiFramework";
import { ClassGroupingOption } from "../Common";
import { VisibilityTreeEventHandler } from "../VisibilityTreeEventHandler";
import { useVisibilityTreeFiltering, useVisibilityTreeRenderer, VisibilityTreeNoFilteredData } from "../VisibilityTreeRenderer";
import { ModelsVisibilityHandler, SubjectModelIdsCache } from "./ModelsVisibilityHandler";
const PAGING_SIZE = 20;
/** @internal */
export const RULESET_MODELS = require("./Hierarchy.json"); // eslint-disable-line @typescript-eslint/no-var-requires
/** @internal */
export const 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.
 */
export function ModelsTree(props) {
    const { nodeLoader, onItemsRendered } = useModelsTreeNodeLoader(props);
    const { filteredNodeLoader, isFiltering, nodeHighlightingProps } = 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.getNodeType(node, nodeLoader.dataProvider));
    }, [selectionPredicate, nodeLoader.dataProvider]);
    const visibilityHandler = useVisibilityHandler(nodeLoader.dataProvider.rulesetId, props.iModel, activeView, modelsVisibilityHandler, getFilteredDataProvider(filteredNodeLoader.dataProvider), props.enableHierarchyAutoUpdate);
    const eventHandler = useDisposable(React.useCallback(() => new VisibilityTreeEventHandler({
        nodeLoader: filteredNodeLoader,
        visibilityHandler,
        collapsedChildrenDisposalEnabled: true,
        selectionPredicate: nodeSelectionPredicate,
    }), [filteredNodeLoader, visibilityHandler, nodeSelectionPredicate]));
    const treeModel = useTreeModel(filteredNodeLoader.modelSource);
    const treeRenderer = useVisibilityTreeRenderer(true, false);
    const overlay = isFiltering ? React.createElement("div", { className: "filteredTreeOverlay" }) : undefined;
    // istanbul ignore next
    const noFilteredDataRenderer = React.useCallback(() => {
        return React.createElement(VisibilityTreeNoFilteredData, { title: UiFramework.localization.getLocalizedString("UiFramework:modelTree.noModelFound"), message: UiFramework.localization.getLocalizedString("UiFramework:modelTree.noMatchingModelNames") });
    }, []);
    return (React.createElement("div", { className: "ui-fw-models-tree", ref: props.rootElementRef },
        React.createElement(ControlledTree, { nodeLoader: filteredNodeLoader, model: treeModel, selectionMode: props.selectionMode || SelectionMode.None, eventsHandler: eventHandler, treeRenderer: treeRenderer, nodeHighlightingProps: nodeHighlightingProps, noDataRenderer: filterApplied ? noFilteredDataRenderer : undefined, onItemsRendered: onItemsRendered, width: props.width, height: props.height }),
        overlay));
}
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) ? { ...RULESET_MODELS } : /* istanbul ignore next */ { ...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 } = usePresentationTreeNodeLoader({
        imodel: props.iModel,
        ruleset: rulesets.general,
        appendChildrenCountForGroupingNodes: (props.enableElementsClassGrouping === ClassGroupingOption.YesWithCounts),
        pagingSize: PAGING_SIZE,
        enableHierarchyAutoUpdate: props.enableHierarchyAutoUpdate,
    });
    const { nodeLoader: searchNodeLoader, onItemsRendered: onSearchItemsRendered } = 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.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 SubjectModelIdsCache(iModel), [iModel]);
    const defaultVisibilityHandler = 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({ 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