"use strict";

var __assign = void 0 && (void 0).__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 = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  Object.defineProperty(o, k2, {
    enumerable: true,
    get: function get() {
      return m[k];
    }
  });
} : function (o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  o[k2] = m[k];
});

var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) {
  Object.defineProperty(o, "default", {
    enumerable: true,
    value: v
  });
} : function (o, v) {
  o["default"] = v;
});

var __importStar = void 0 && (void 0).__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 = void 0 && (void 0).__importDefault || function (mod) {
  return mod && mod.__esModule ? mod : {
    "default": mod
  };
};

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.CascadeCheckListMemo = void 0;

var jsx_runtime_1 = require("react/jsx-runtime");

var React = __importStar(require("react"));

var react_1 = require("react");

var icon_1 = require("../../icon");

require("../style/cascade-check-list.css");

var List_1 = __importStar(require("./List"));

var debounce_1 = __importDefault(require("lodash/debounce"));

var map_1 = __importDefault(require("lodash/map"));

var prefixCls = 'dmc-cascade-check-list';
var debug = false; // eslint-disable-next-line

var console = debug ? window.console : __assign(__assign({}, window.console), {
  log: function log() {
    var _args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      _args[_i] = arguments[_i];
    }
  }
}); // checklist 间距

var listGap = 5; // 判断是否需要关闭子菜单的延迟时间

var enterListDelay = 300; // 光标进入行 去抖

var debounceEnterLineDelay = 300; // 判断光标离开行延迟时间

var leaveLineDelay = 400; // 全局状态 指示各层次光标进入

var mouseEnterListFlag = {}; // 全局状态 指示各行光标进入

var mouseEnterLineFlag = {}; // 计算节点勾选状态

var computeCheckedStatus = function computeCheckedStatus(id, subNodesStatistic, checkedNodesIds) {
  var cnt = 0;
  var checkedCnt = 0;
  var checked = false;
  var indeterminate = false;
  var subNodesObj = subNodesStatistic[id]; // 非叶子节点

  if (subNodesObj) {
    var curNodeSubNodesIds = Object.keys(subNodesObj);
    var curNodeSubNodesIdsCnt = curNodeSubNodesIds.length;

    for (var i = 0; i < curNodeSubNodesIdsCnt; i++) {
      if (curNodeSubNodesIds[i] in checkedNodesIds) {
        cnt++;
      }
    }

    if (cnt > 0) {
      indeterminate = true;
      checkedCnt++;
    }

    if (cnt === curNodeSubNodesIdsCnt) {
      checked = true;
    }
  } else if (id in checkedNodesIds) {
    checked = true;
    checkedCnt++;
  }

  return {
    checked: checked,
    indeterminate: indeterminate,
    checkedCnt: checkedCnt
  };
};

var CascadeCheckList = React.memo(React.forwardRef(function (props, ref) {
  var _a, _b, _c, _d, _e;

  var levelTitles = props.levelTitles,
      data = props.data,
      leveNodesStatistic = props.leveNodesStatistic,
      subNodesStatistic = props.subNodesStatistic,
      _f = props.level,
      level = _f === void 0 ? 0 : _f,
      checkedNodesIdsObj = props.checkedNodesIdsObj,
      updateCheckedNodesIdsObj = props.updateCheckedNodesIdsObj,
      showSearchLevel = props.showSearchLevel,
      levelSearchInputPlaceholder = props.levelSearchInputPlaceholder,
      levelShowCheckbox = props.levelShowCheckbox,
      levelSelectAll = props.levelSelectAll,
      levelSelectAllText = props.levelSelectAllText,
      renderer = props.renderer,
      customRendererLevel = props.customRendererLevel,
      _g = props.control,
      control = _g === void 0 ? false : _g,
      initCheckedIds = props.initCheckedIds,
      onChange = props.onChange,
      style = props.style,
      maxLevel = props.maxLevel,
      handleMount = props.handleMount,
      rowWidth = props.rowWidth,
      rowMinWidth = props.rowMinWidth,
      rowMaxWidth = props.rowMaxWidth,
      _h = props.triggerType,
      triggerType = _h === void 0 ? 'hover' : _h;
  var wrapperRef = react_1.useRef(null);
  var childListRef = react_1.useRef(null); // 当前激活项目（通过 hover / click菜单项) data-id

  var currentActiveElementId = react_1.useRef(undefined);
  var ComponentMountRef = react_1.useRef(true); // activeIndex 为内部状态 控制显示子菜单，状态非实时更新（debounce)

  var _j = react_1.useState(null),
      activeIndex = _j[0],
      setActiveIndex = _j[1];

  var _k = react_1.useState(null),
      curHoverTargetPos = _k[0],
      setCurHoverTargetPos = _k[1];

  var _l = react_1.useState(''),
      hoverItemId = _l[0],
      setHoverItemId = _l[1];

  var _m = react_1.useState(false),
      isChildMounted = _m[0],
      setChildMounted = _m[1];

  var showSearch = (_a = showSearchLevel === null || showSearchLevel === void 0 ? void 0 : showSearchLevel.includes(level)) !== null && _a !== void 0 ? _a : false;
  var showCheckbox = (_b = levelShowCheckbox === null || levelShowCheckbox === void 0 ? void 0 : levelShowCheckbox.includes(level)) !== null && _b !== void 0 ? _b : true;
  var searchInputPlaceholder = (_c = levelSearchInputPlaceholder === null || levelSearchInputPlaceholder === void 0 ? void 0 : levelSearchInputPlaceholder[level]) !== null && _c !== void 0 ? _c : '';
  var applyCustomRenderer = (_d = customRendererLevel === null || customRendererLevel === void 0 ? void 0 : customRendererLevel.includes(level)) !== null && _d !== void 0 ? _d : true;
  var selectAll = (_e = levelSelectAll === null || levelSelectAll === void 0 ? void 0 : levelSelectAll.includes(level)) !== null && _e !== void 0 ? _e : true;
  var selectAllText = (levelSelectAllText === null || levelSelectAllText === void 0 ? void 0 : levelSelectAllText[level]) || undefined; // 子级列表样式

  var _o = react_1.useState({
    position: 'absolute',
    top: '-9999px',
    left: '-9999px',
    zIndex: 9999
  }),
      dropDownPositionStyle = _o[0],
      setDropDownPositionStyle = _o[1];

  var subData = react_1.useMemo(function () {
    var subNodesData = leveNodesStatistic[hoverItemId] || {};
    return Object.values(subNodesData);
  }, [leveNodesStatistic, hoverItemId]);
  var options = react_1.useMemo(function () {
    return map_1["default"](data, function (_a) {
      var id = _a.id,
          val = _a.val,
          _id = _a._id;
      return {
        id: id,
        _id: _id,
        val: val
      };
    }) || [];
  }, [data]);
  var getEnterChildListFlag = react_1.useCallback(function (level) {
    var _a;

    var flag = false;

    for (var l = level + 1; l < maxLevel; l++) {
      var levelEnterFlag = (_a = mouseEnterListFlag[l]) !== null && _a !== void 0 ? _a : false;

      if (levelEnterFlag) {
        flag = true;
        break;
      }
    }

    return flag;
  }, [maxLevel]);
  var refCallback = react_1.useCallback(function (node) {
    if (ref instanceof Function) {
      ref(node);
    } else if (ref) {
      ref.current = node;
    }

    wrapperRef.current = node;
  }, [ref]); // 勾选状态计算

  var checkedStatus = react_1.useMemo(function () {
    var checkedObj = {};
    var indeterminateObj = {};
    var optionsCnt = options.length;
    var checkedCnt = 0;

    for (var i = 0; i < optionsCnt; i++) {
      var id = options[i].id;

      var _a = computeCheckedStatus(id, subNodesStatistic, checkedNodesIdsObj),
          checked = _a.checked,
          indeterminate = _a.indeterminate,
          _checkedCnt = _a.checkedCnt;

      checkedCnt += _checkedCnt;
      checkedObj[id] = checked;
      indeterminateObj[id] = indeterminate;
    }

    return {
      checkedCnt: checkedCnt,
      checkedObj: checkedObj,
      indeterminateObj: indeterminateObj
    };
  }, [checkedNodesIdsObj, options, subNodesStatistic]);
  var handleClearActiveIndex = react_1.useCallback(function (callback) {
    var enterChildListFlag = getEnterChildListFlag(level);

    if (mouseEnterLineFlag[level] === null && !enterChildListFlag && ComponentMountRef.current) {
      callback();
    }
  }, [getEnterChildListFlag, level]);
  var handleMouseEnter = react_1.useCallback(function () {
    if (triggerType === 'hover') {
      mouseEnterListFlag[level] = true;
      setTimeout(function () {
        // 从子级返回父级非数据行时
        handleClearActiveIndex(function () {
          setActiveIndex(null);
        });
      }, enterListDelay);
      console.log('enter: ', level, mouseEnterListFlag);
    }
  }, [handleClearActiveIndex, level, triggerType]);
  var handleMouseLeave = react_1.useCallback(function () {
    if (triggerType === 'hover') {
      console.log('trigger leave');
      var enterChildListFlag = getEnterChildListFlag(level);

      if (!enterChildListFlag) {
        // 光标未进入子菜单下的 mouseleave 表明也离开了当前层级
        mouseEnterListFlag[level] = false;
        console.log('leave: ', level);
      }

      setTimeout(function () {
        handleClearActiveIndex(function () {
          setActiveIndex(null);
        });
      }, enterListDelay);
    }
  }, [getEnterChildListFlag, handleClearActiveIndex, level, triggerType]); // eslint-disable-next-line react-hooks/exhaustive-deps

  var _handleEnterLine = react_1.useCallback(debounce_1["default"](function (pos, id, index) {
    if (ComponentMountRef.current) {
      var nextLevel = level + 1;

      if (!mouseEnterListFlag[nextLevel]) {
        setActiveIndex(index);
        setCurHoverTargetPos(pos);
        setHoverItemId(id);
      }
    }
  }, triggerType === 'hover' ? debounceEnterLineDelay : 0), [level]); // 光标触发打开子菜单


  var handleActiveLine = react_1.useCallback(function (pos, id, _val, index, dom) {
    mouseEnterLineFlag[level] = index;
    currentActiveElementId.current = dom.dataset.id;
    console.log('enter line', index);

    _handleEnterLine(pos, id, index);
  }, [_handleEnterLine, level]); // 关闭子菜单

  var handleInactiveLine = react_1.useCallback(function () {
    mouseEnterLineFlag[level] = null;
    setTimeout(function () {
      handleClearActiveIndex(function () {
        console.log('leave line');
        setActiveIndex(null);
        setHoverItemId('');
      });
    }, leaveLineDelay);
  }, [handleClearActiveIndex, level]); // 更新勾选状态

  var _handleChange = react_1.useCallback(function (id, _id, _val, checked, checkedNodesVals) {
    var toChangeNodesIds = [id];
    var toChangeNodesVals = [_id || id];
    var curNodeLeafNodesObj = subNodesStatistic[id];

    if (curNodeLeafNodesObj) {
      toChangeNodesIds = Object.keys(curNodeLeafNodesObj);
      toChangeNodesVals = Object.values(curNodeLeafNodesObj);
    }

    var nodeCnt = toChangeNodesIds.length;

    for (var i = 0; i < nodeCnt; i++) {
      var nodeId = toChangeNodesIds[i];
      var nodeVal = toChangeNodesVals[i];

      if (checked) {
        checkedNodesVals[nodeId] = nodeVal;
      } else {
        delete checkedNodesVals[nodeId];
      }
    }

    console.log('checkedNodesVals: ', checkedNodesVals);
  }, [subNodesStatistic]);

  var handleCheckboxChange = react_1.useCallback(function (id, _id, val, checked) {
    var tmpCheckNodesIdsOjb = __assign({}, checkedNodesIdsObj);

    _handleChange(id, _id, val, checked, tmpCheckNodesIdsOjb);

    if (!control) {
      updateCheckedNodesIdsObj === null || updateCheckedNodesIdsObj === void 0 ? void 0 : updateCheckedNodesIdsObj(tmpCheckNodesIdsOjb || {});
    }

    onChange === null || onChange === void 0 ? void 0 : onChange(Object.keys(tmpCheckNodesIdsOjb), tmpCheckNodesIdsOjb);
  }, [checkedNodesIdsObj, updateCheckedNodesIdsObj, _handleChange, control, onChange]);
  var handleCheckedAllChange = react_1.useCallback(function (checked) {
    var tmpCheckNodesIdsOjb = __assign({}, checkedNodesIdsObj);

    var optionsLen = options.length;

    for (var i = 0; i < optionsLen; i++) {
      var _a = options[i],
          id = _a.id,
          _id = _a._id,
          val = _a.val;

      _handleChange(id, _id, val, checked, tmpCheckNodesIdsOjb);
    }

    if (!control) {
      updateCheckedNodesIdsObj === null || updateCheckedNodesIdsObj === void 0 ? void 0 : updateCheckedNodesIdsObj(tmpCheckNodesIdsOjb || {});
    }

    onChange === null || onChange === void 0 ? void 0 : onChange(Object.keys(tmpCheckNodesIdsOjb), tmpCheckNodesIdsOjb);
  }, [checkedNodesIdsObj, updateCheckedNodesIdsObj, _handleChange, control, onChange, options]);
  var handleChildListMount = react_1.useCallback(function (childListMount) {
    setChildMounted(childListMount);
  }, []);
  var getOffsetParentTop = react_1.useCallback(function (el) {
    var curEl = el;
    var offsetTop = 0;

    while (curEl && !curEl.classList.contains(prefixCls)) {
      offsetTop += curEl.offsetTop || 0;
      curEl = curEl.offsetParent || null;
    }

    return offsetTop;
  }, []);
  react_1.useEffect(function () {
    ComponentMountRef.current = true;
    handleMount === null || handleMount === void 0 ? void 0 : handleMount(true);
    return function () {
      ComponentMountRef.current = false;
      handleMount === null || handleMount === void 0 ? void 0 : handleMount(false);
    };
  }, [handleMount]);
  react_1.useEffect(function () {
    var listRef = wrapperRef.current;
    var activeElementId = currentActiveElementId.current;

    if (isChildMounted && curHoverTargetPos && listRef && activeElementId) {
      var activeElement = listRef.querySelector("." + List_1.virtualizedListWrapperClassName + " [data-id=\"" + activeElementId + "\"]");

      if (!activeElement) {
        console.error('cascade checklist error: failed to found active element'); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore

        console._error('cascade checklist error: failed to found active element');

        return;
      }

      var offsetTopOfList = getOffsetParentTop(activeElement);
      var top_1 = curHoverTargetPos.top,
          left = curHoverTargetPos.left,
          targetWidth = curHoverTargetPos.width;
      var childList = childListRef.current;

      if (childList) {
        var newTop_1 = offsetTopOfList;
        var newLeft_1 = targetWidth + listGap;

        var _a = childList.getBoundingClientRect(),
            childListWidth = _a.width,
            childListHeight = _a.height;

        var innerWidth_1 = window.innerWidth,
            innerHeight_1 = window.innerHeight;
        var childBottomToClientTop = top_1 + childListHeight;
        var childRightToClientRight = newLeft_1 + left + childListWidth; // 检测屏幕边缘

        if (childBottomToClientTop > innerHeight_1) {
          newTop_1 -= childBottomToClientTop - innerHeight_1;
        }

        if (childRightToClientRight > innerWidth_1) {
          newLeft_1 -= childRightToClientRight - innerWidth_1;
        }

        var virtualListDom_1 = listRef.querySelector('.ReactVirtualized__List');
        setDropDownPositionStyle(function (prev) {
          return __assign(__assign({}, prev), {
            // 减去纵向滚动值
            top: newTop_1 - ((virtualListDom_1 === null || virtualListDom_1 === void 0 ? void 0 : virtualListDom_1.scrollTop) || 0) + "px",
            left: newLeft_1 + "px"
          });
        });
      }
    }
  }, [childListRef, curHoverTargetPos, getOffsetParentTop, isChildMounted]);

  var _renderer = react_1.useCallback(function (id, _id, val, _checked, item, index) {
    var subNodesData = leveNodesStatistic[item.id] || {};
    return jsx_runtime_1.jsx(jsx_runtime_1.Fragment, {
      children: renderer && applyCustomRenderer ? jsx_runtime_1.jsx("div", __assign({
        className: prefixCls + "-custom-item-wrap",
        onClick: function onClick() {
          return handleCheckboxChange(id, _id, val, !checkedStatus.checkedObj[id]);
        }
      }, {
        children: renderer(index, val, checkedStatus, !subNodesStatistic[id])
      }), void 0) : jsx_runtime_1.jsxs("span", __assign({
        className: prefixCls + "-row-content"
      }, {
        children: [jsx_runtime_1.jsx("span", __assign({
          className: "content"
        }, {
          children: val
        }), void 0), Object.keys(subNodesData).length > 0 && jsx_runtime_1.jsx(icon_1.Icon, {
          icon: "play",
          size: 16
        }, void 0)]
      }), void 0)
    }, void 0);
  }, [leveNodesStatistic, subNodesStatistic, applyCustomRenderer, checkedStatus, handleCheckboxChange, renderer]);

  return jsx_runtime_1.jsxs("div", __assign({
    className: prefixCls,
    ref: refCallback,
    onMouseEnter: handleMouseEnter,
    onMouseLeave: handleMouseLeave,
    style: style
  }, {
    children: [jsx_runtime_1.jsx(List_1["default"], {
      rowWidth: rowWidth,
      rowMinWidth: rowMinWidth,
      rowMaxWidth: rowMaxWidth,
      selectAll: selectAll,
      selectAllText: selectAllText,
      showCheckbox: showCheckbox,
      showSearch: showSearch,
      searchInputPlaceholder: searchInputPlaceholder,
      options: options,
      renderer: _renderer,
      level: level,
      levelTitles: levelTitles,
      checkedStatus: checkedStatus,
      handleMouseEnterLine: handleActiveLine,
      handleMouseLeaveLine: handleInactiveLine,
      handleCheckboxChange: handleCheckboxChange,
      handleCheckedAllChange: handleCheckedAllChange,
      triggerType: triggerType
    }, void 0), activeIndex !== null && subData.length > 0 && jsx_runtime_1.jsx(CascadeCheckList, {
      ref: childListRef,
      rowWidth: rowWidth,
      rowMinWidth: rowMinWidth,
      rowMaxWidth: rowMaxWidth,
      style: dropDownPositionStyle,
      renderer: renderer,
      customRendererLevel: customRendererLevel,
      level: level + 1,
      levelTitles: levelTitles,
      data: subData,
      leveNodesStatistic: leveNodesStatistic,
      subNodesStatistic: subNodesStatistic,
      checkedNodesIdsObj: checkedNodesIdsObj,
      updateCheckedNodesIdsObj: updateCheckedNodesIdsObj,
      showSearchLevel: showSearchLevel,
      levelSearchInputPlaceholder: levelSearchInputPlaceholder,
      levelShowCheckbox: levelShowCheckbox,
      onChange: onChange,
      control: control,
      initCheckedIds: initCheckedIds,
      levelSelectAll: levelSelectAll,
      levelSelectAllText: levelSelectAllText,
      maxLevel: maxLevel,
      handleMount: handleChildListMount,
      triggerType: triggerType
    }, void 0)]
  }), void 0);
}));
CascadeCheckList.displayName = 'CascadeCheckList';
exports["default"] = CascadeCheckList;
var CascadeCheckListMemo = React.memo(CascadeCheckList);
exports.CascadeCheckListMemo = CascadeCheckListMemo;
CascadeCheckListMemo.displayName = 'CascadeCheckListMemo';

