import React, { useCallback, useState, useEffect } from 'react';
import { makeStyles, useTheme, lighten, CircularProgress, Typography } from '@material-ui/core';
import TreeView from '@material-ui/lab/TreeView';
import { WorkflowTreeMenuItem } from './WorkflowTreeMenuItem';
import { searchTree, findAllParentIds, getNodeIdForRightBorder } from '../../utilities/tree/TreeUtilities';
import { FluentIcon } from '../../utilities/iconLibrary/FluentIcon';
import { CaretUpSolid8Icon, CaretDownSolid8Icon } from '@fluentui/react-icons';
import { cloneDeep } from 'lodash-es';
import { TreeViewModeEnums } from '../../enums/unitySystemEnums.ts';
const useStyles = makeStyles((theme) => ({
    root: {
        marginBottom: theme.spacing(1.75),
        borderTop: (props) => props.treeViewMode === TreeViewModeEnums.Compact
            ? `1px solid ${theme.palette.grey[200]}`
            : ''
    },
    noChildrenContainer: {
        borderBottom: (props) => props.treeViewMode === TreeViewModeEnums.Compact
            ? `1px solid ${theme.palette.grey[200]}`
            : ''
    }
}));
export const WorkflowTreeMenu = (props) => {
    const { menuItems, onSelectNode, onDropNode, menuIndex, selectedNodeId, selectedNodeParentId, sidebarExpanded, treeViewMode, childrenKey = 'children' } = props;
    const [expanded, setExpanded] = useState(null);
    const [isCurrentActiveTree, setIsCurrentActiveTree] = useState(false);
    const [selectedNodeIsHidden, setSelectedNodeIsHidden] = useState(false);
    const [tree, setTree] = useState(menuItems);
    const theme = useTheme();
    const classes = useStyles(props);
    const handleSelectedNode = useCallback((e, value) => {
        const selectedNode = searchTree(tree, value);
        if (onSelectNode) {
            onSelectNode(selectedNode, menuIndex);
            setSelectedNodeIsHidden(false);
        }
    }, [tree, menuIndex, onSelectNode]);
    const renderTree = useCallback((node, depth = 1) => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
        let label = ((_a = node.properties) === null || _a === void 0 ? void 0 : _a.nodeLabel) || ((_b = node.properties) === null || _b === void 0 ? void 0 : _b.name);
        let subLabel = (_c = node.properties) === null || _c === void 0 ? void 0 : _c.nodeSubLabel;
        let iconName = (_e = (_d = node.properties) === null || _d === void 0 ? void 0 : _d.defaultIcon) === null || _e === void 0 ? void 0 : _e.name;
        let iconType = (_g = (_f = node.properties) === null || _f === void 0 ? void 0 : _f.defaultIcon) === null || _g === void 0 ? void 0 : _g.type;
        let conditionalIconName = ((_j = (_h = node.properties) === null || _h === void 0 ? void 0 : _h.conditionalIcon) === null || _j === void 0 ? void 0 : _j.name) || '';
        let conditionalIconType = ((_l = (_k = node.properties) === null || _k === void 0 ? void 0 : _k.conditionalIcon) === null || _l === void 0 ? void 0 : _l.name)
            ? (_m = node.properties.conditionalIcon) === null || _m === void 0 ? void 0 : _m.type
            : '';
        let conditionalIconColor = ((_p = (_o = node.properties) === null || _o === void 0 ? void 0 : _o.conditionalIcon) === null || _p === void 0 ? void 0 : _p.name)
            ? (_r = (_q = node.properties) === null || _q === void 0 ? void 0 : _q.conditionalIcon) === null || _r === void 0 ? void 0 : _r.color
            : '';
        let nodeId = node.id;
        let iconColor = ((_s = node.properties) === null || _s === void 0 ? void 0 : _s.conditionalIconName)
            ? (_t = node.properties) === null || _t === void 0 ? void 0 : _t.conditionalIconColor
            : (_w = (_v = (_u = node.properties) === null || _u === void 0 ? void 0 : _u.defaultIcon) === null || _v === void 0 ? void 0 : _v.color) === null || _w === void 0 ? void 0 : _w.hex;
        let aggregateThresholdId = ((_x = node.properties) === null || _x === void 0 ? void 0 : _x.aggregateThresholdId) || '';
        if (node.isGroupNode) {
            label = (_y = node.properties) === null || _y === void 0 ? void 0 : _y.label;
            subLabel = (_z = node.properties) === null || _z === void 0 ? void 0 : _z.subLabel;
            iconName = (_1 = (_0 = node.properties) === null || _0 === void 0 ? void 0 : _0.icon) === null || _1 === void 0 ? void 0 : _1.name;
            iconType = (_3 = (_2 = node.properties) === null || _2 === void 0 ? void 0 : _2.icon) === null || _3 === void 0 ? void 0 : _3.type;
            iconColor = (_6 = (_5 = (_4 = node.properties) === null || _4 === void 0 ? void 0 : _4.icon) === null || _5 === void 0 ? void 0 : _5.color) === null || _6 === void 0 ? void 0 : _6.hex;
        }
        return (React.createElement(WorkflowTreeMenuItem, { key: nodeId, nodeId: nodeId, label: label, subLabel: subLabel, iconName: iconName, iconType: iconType, conditionalIconName: conditionalIconName, conditionalIconType: conditionalIconType, conditionalIconColor: conditionalIconColor, parentId: node.parentId, iconColor: iconColor, onNodeSelect: handleSelectedNode, selectedNodeId: selectedNodeId, isSelectedNode: selectedNodeId === node.id, showRightBorderColor: selectedNodeIsHidden &&
                isCurrentActiveTree &&
                getNodeIdForRightBorder(expanded, tree, selectedNodeParentId) ===
                    node.id, isCurrentActiveTree: isCurrentActiveTree, sidebarExpanded: sidebarExpanded, depth: depth, hideExpansion: !!!((_7 = node[childrenKey]) === null || _7 === void 0 ? void 0 : _7.length), node: node, onDropNode: onDropNode, treeViewMode: treeViewMode, menuIndex: menuIndex, aggregateThresholdId: aggregateThresholdId }, ((_8 = node.properties) === null || _8 === void 0 ? void 0 : _8.lazyLoad) &&
            !!!((_9 = node[childrenKey]) === null || _9 === void 0 ? void 0 : _9.length) &&
            !node.completedLoadingChildren && (React.createElement(CircularProgress, { size: 12, style: { marginLeft: (depth || 1) * theme.spacing(1) } })), ((_10 = node.properties) === null || _10 === void 0 ? void 0 : _10.lazyLoad) &&
            !!!((_11 = node[childrenKey]) === null || _11 === void 0 ? void 0 : _11.length) &&
            node.completedLoadingChildren &&
            sidebarExpanded &&
            !node.errorRetrievingChildren && (React.createElement("div", { className: classes.noChildrenContainer }, React.createElement(Typography, { variant: "caption", style: {
                marginLeft: (depth || 1) * theme.spacing(3),
                fontWeight: 400
            } }, "No Childre"))), ((_12 = node.properties) === null || _12 === void 0 ? void 0 : _12.lazyLoad) &&
            node.completedLoadingChildren &&
            sidebarExpanded &&
            node.errorRetrievingChildren && (React.createElement("div", { className: classes.noChildrenContainer }, React.createElement(Typography, { variant: "caption", style: {
                marginLeft: (depth || 1) * theme.spacing(3),
                fontWeight: 400
            } }, `Error Retrieving ${!!((_13 = node[childrenKey]) === null || _13 === void 0 ? void 0 : _13.length) ? `Additional ` : ''}Children`))), Array.isArray(node[childrenKey])
            ? node[childrenKey].map((n, i) => renderTree(n, depth + 1))
            : null));
    }, [
        handleSelectedNode,
        selectedNodeId,
        selectedNodeIsHidden,
        isCurrentActiveTree,
        sidebarExpanded,
        expanded,
        tree,
        selectedNodeParentId,
        theme,
        classes,
        onDropNode,
        treeViewMode,
        menuIndex,
        childrenKey
    ]);
    const handleNodeExpansion = useCallback(async (evt, nodeIds) => {
        const treeCopy = cloneDeep(tree);
        setExpanded(nodeIds);
        const parentNode = searchTree(treeCopy, selectedNodeParentId);
        const initialAllParentNodeIds = selectedNodeParentId
            ? [selectedNodeParentId]
            : [];
        const allParentNodeIds = findAllParentIds(treeCopy, parentNode, initialAllParentNodeIds);
        const selectedNodeShown = allParentNodeIds.every((id) => nodeIds.includes(id));
        if (isCurrentActiveTree &&
            allParentNodeIds.length &&
            !selectedNodeShown) {
            setSelectedNodeIsHidden(true);
        }
        else {
            setSelectedNodeIsHidden(false);
        }
    }, [isCurrentActiveTree, tree, selectedNodeParentId]);
    const getExpandedRecursively = useCallback((tree) => {
        if (!tree)
            return [];
        return tree.reduce((expandedIds, item) => {
            var _a;
            if (item === null || item === void 0 ? void 0 : item.isExpanded) {
                expandedIds.push(item.id);
            }
            if (item && ((_a = item[childrenKey]) === null || _a === void 0 ? void 0 : _a.length)) {
                expandedIds = expandedIds.concat(getExpandedRecursively(item[childrenKey]));
            }
            return expandedIds;
        }, []);
    }, [childrenKey]);
    useEffect(() => {
        setTree(menuItems);
    }, [menuItems]);
    useEffect(() => {
        if (!tree) {
            return;
        }
        let expanded = [];
        if (tree === null || tree === void 0 ? void 0 : tree.isExpanded) {
            expanded.push(tree.id);
        }
        expanded = expanded.concat(getExpandedRecursively(tree[childrenKey]));
        setExpanded(expanded);
    }, [getExpandedRecursively, tree, childrenKey]);
    useEffect(() => {
        if (!!searchTree(tree, selectedNodeId)) {
            setIsCurrentActiveTree(true);
        }
        else {
            setIsCurrentActiveTree(false);
        }
    }, [tree, selectedNodeId]);
    if (!expanded) {
        return null;
    }
    return (React.createElement(TreeView, { key: tree, className: classes.root, defaultCollapseIcon: React.createElement(FluentIcon, { size: "small", component: CaretUpSolid8Icon, style: {
                color: lighten(theme.palette.primary.main, 0.5),
                width: theme.spacing(1.5),
                height: theme.spacing(1.5)
            } }), expanded: expanded || [], onNodeToggle: handleNodeExpansion, defaultExpandIcon: React.createElement(FluentIcon, { size: "small", component: CaretDownSolid8Icon, style: {
                color: lighten(theme.palette.primary.main, 0.5),
                width: theme.spacing(1.5),
                height: theme.spacing(1.5)
            } }), selected: selectedNodeId }, tree && renderTree(tree)));
};
//# sourceMappingURL=WorkflowTreeMenu.js.map