"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RCTree = void 0;
var classnames_1 = __importDefault(require("classnames"));
var ramda_1 = require("ramda");
var rc_tree_1 = __importDefault(require("rc-tree"));
var react_1 = __importStar(require("react"));
var DragIndicator_1 = __importDefault(require("@mui/icons-material/DragIndicator"));
var react_resize_detector_1 = __importDefault(require("react-resize-detector"));
var mdm_sdk_1 = require("@reltio/mdm-sdk");
var RCTreeSwitchRenderer_1 = require("./RCTreeSwitchRenderer");
var RCTreeLevelLines_1 = require("./RCTreeLevelLines");
var helper_1 = require("./helper");
var useDnd_1 = require("./useDnd");
var styles_1 = require("./styles");
var MIN_ROW_HEIGHT = 28;
var returnFalse = function () { return false; };
var RCTree = function (_a) {
    var _b;
    var treeData = _a.treeData, _c = _a.isVirtualized, isVirtualized = _c === void 0 ? true : _c, _d = _a.canDrag, canDragProp = _d === void 0 ? returnFalse : _d, _e = _a.canDrop, canDrop = _e === void 0 ? returnFalse : _e, _f = _a.onDrop, onDrop = _f === void 0 ? mdm_sdk_1.noop : _f, onLoadChildren = _a.onLoadChildren, _g = _a.defaultExpandAll, defaultExpandAll = _g === void 0 ? false : _g, _h = _a.SwitchRenderer, SwitchRenderer = _h === void 0 ? RCTreeSwitchRenderer_1.RCTreeSwitchRenderer : _h, _j = _a.LevelLinesRenderer, LevelLinesRenderer = _j === void 0 ? RCTreeLevelLines_1.RCTreeLevelLines : _j, className = _a.className, renderNode = _a.renderNode, _k = _a.minItemHeight, minItemHeight = _k === void 0 ? MIN_ROW_HEIGHT : _k, _l = _a.isLeaf, isLeaf = _l === void 0 ? helper_1.defaultIsLeaf : _l, scrollToNode = _a.scrollToNode, _m = _a.onChange, onChange = _m === void 0 ? ramda_1.identity : _m, height = _a.height;
    var styles = (0, styles_1.useStyles)();
    var treeRef = (0, react_1.useRef)(null);
    var containerRef = (0, react_1.useRef)(null);
    var _o = (0, react_1.useState)({ width: 0, height: 0 }), containerSize = _o[0], setContainerSize = _o[1];
    var _p = (0, react_1.useState)(true), isDraggingEnabled = _p[0], setIsDraggingEnabled = _p[1];
    var expandNode = (0, react_1.useCallback)(function (pos, expanded) {
        var changeNode = (0, ramda_1.assoc)('expanded', expanded);
        var newTreeData = (0, helper_1.changeNodeAtPosition)(treeData, pos, changeNode);
        if (newTreeData)
            onChange(newTreeData);
    }, [onChange, treeData]);
    var canDrag = (0, react_1.useCallback)(function (params) { return isDraggingEnabled && canDragProp(params); }, [canDragProp, isDraggingEnabled]);
    var _q = (0, useDnd_1.useDnd)({
        containerRef: containerRef,
        treeData: treeData,
        expandNode: expandNode,
        onLoadChildren: onLoadChildren,
        onChange: onChange,
        onDrop: onDrop,
        canDrop: canDrop,
        canDrag: canDrag
    }), treeProps = _q.treeProps, nodeDraggable = _q.nodeDraggable, dropNode = _q.dropNode, dragNode = _q.dragNode, dropPositionInfo = _q.dropPositionInfo;
    (0, react_1.useEffect)(function () {
        if (treeRef.current && scrollToNode) {
            treeRef.current.scrollTo({ key: String(scrollToNode.nodeId) });
        }
    }, [scrollToNode]);
    var diplayedTreeData = (0, react_1.useMemo)(function () {
        if (dropNode && dragNode && dropPositionInfo) {
            if (dropNode.pos === dragNode.pos && dropNode.key === dragNode.key)
                return treeData;
            var dragNodeValue = __assign(__assign({}, dragNode.value), { nodeId: -1 });
            return (0, helper_1.moveNode)(treeData, dragNodeValue, dragNode.pos, dropPositionInfo);
        }
        return treeData;
    }, [treeData, dragNode, dropNode, dropPositionInfo]);
    var expandedKeys = (0, react_1.useMemo)(function () {
        return (0, helper_1.getExpandedKeys)(diplayedTreeData);
    }, [diplayedTreeData]);
    var levelLines = (0, react_1.useMemo)(function () { return (0, helper_1.getLevelLinesData)(diplayedTreeData); }, [diplayedTreeData]);
    var internalTreeData = (0, react_1.useMemo)(function () { return (0, helper_1.convertTreeData)({ data: diplayedTreeData, isLeaf: isLeaf }); }, [isLeaf, diplayedTreeData]);
    var handleExpand = (0, react_1.useCallback)(function (_expandedKeys, data) {
        if (onChange && !dragNode) {
            expandNode(data.node.pos, data.expanded);
        }
    }, [onChange, expandNode, dragNode]);
    var renderSwitcherIcon = (0, react_1.useCallback)(function (node) { return react_1.default.createElement(SwitchRenderer, { node: node }); }, [SwitchRenderer]);
    var handleEnableDragging = (0, react_1.useCallback)(function () {
        setIsDraggingEnabled(true);
        window.removeEventListener('mouseup', handleEnableDragging);
        window.removeEventListener('dragend', handleEnableDragging);
    }, []);
    var handleDisableDragging = (0, react_1.useCallback)(function () {
        setIsDraggingEnabled(false);
        window.addEventListener('mouseup', handleEnableDragging);
        window.addEventListener('dragend', handleEnableDragging);
    }, [handleEnableDragging]);
    (0, react_1.useEffect)(function () {
        return function () {
            window.removeEventListener('mouseup', handleEnableDragging);
            window.removeEventListener('dragend', handleEnableDragging);
        };
    }, [handleEnableDragging]);
    var titleRender = function (node) {
        var _a;
        var _b, _c;
        var draggedNodes = (0, helper_1.gatherNodeKeys)(dragNode);
        var width = (0, helper_1.calcNodeWidth)((_c = (_b = levelLines[node.key]) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.length, containerSize.width);
        return (react_1.default.createElement("div", { "data-reltio-id": "rc-tree-title-wrapper", className: (0, classnames_1.default)(styles.titleWrapper, (_a = {},
                _a[styles.dropIndicator] = (0, helper_1.isDropIndicatorNode)(node),
                _a[styles.dropNotAllowed] = dropNode && !(0, helper_1.isDropIndicatorNode)(dropNode),
                _a[styles.draggedChildrenNode] = draggedNodes.includes(node.key),
                _a)), onMouseDown: handleDisableDragging, style: { width: width } },
            react_1.default.createElement(LevelLinesRenderer, { levelLine: levelLines[node.key] }),
            renderNode ? renderNode(node.value) : node.title));
    };
    var dragHandle = (react_1.default.createElement("span", { className: (0, classnames_1.default)(styles.dragHandle, (_b = {}, _b[styles.dragHandleDragging] = !!dragNode, _b)) },
        react_1.default.createElement(DragIndicator_1.default, null)));
    var onContainerResize = (0, react_1.useCallback)(function (width, height) {
        setContainerSize({ width: width, height: height });
    }, []);
    var scrollWidth = (0, react_1.useMemo)(function () {
        return isVirtualized ? Math.max((0, helper_1.getTreeMaxWidth)(diplayedTreeData), containerSize.width) : null;
    }, [diplayedTreeData, isVirtualized, containerSize.width]);
    return diplayedTreeData ? (react_1.default.createElement("div", { ref: containerRef, className: (0, classnames_1.default)(styles.treeContainer) },
        react_1.default.createElement(react_resize_detector_1.default, { handleWidth: true, handleHeight: true, onResize: onContainerResize }),
        react_1.default.createElement(rc_tree_1.default, __assign({ draggable: {
                icon: dragHandle,
                nodeDraggable: nodeDraggable
            }, virtual: isVirtualized, itemHeight: minItemHeight, height: height || containerSize.height, onExpand: handleExpand, showIcon: false, switcherIcon: renderSwitcherIcon, defaultExpandAll: defaultExpandAll, expandedKeys: expandedKeys, className: (0, classnames_1.default)(className, styles.treeWrapper), titleRender: titleRender, treeData: internalTreeData, selectable: false, loadData: onLoadChildren ? function (node) { return onLoadChildren(node.value); } : undefined, scrollWidth: scrollWidth, "data-reltio-id": "rc-tree", ref: treeRef }, treeProps)))) : null;
};
exports.RCTree = RCTree;
