'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
var iconsVue = require('@ant-design/icons-vue');
require('../../../../utils/index.cjs');
require('../../../../hooks/index.cjs');
require('../../../../vue-components/index.cjs');
var index$4 = require('../../../checkbox/index.cjs');
var index$3 = require('../../../dropdown/index.cjs');
var index$2 = require('../../../menu/index.cjs');
var index$5 = require('../../../radio/index.cjs');
var index = require('../../../../hooks/use-merged-state/index.cjs');
var treeUtil = require('../../../../vue-components/vc-tree/src/utils/treeUtil.cjs');
var log = require('../../../../utils/log.cjs');
var useMaxLevel = require('../../../../vue-components/vc-tree/src/useMaxLevel.cjs');
var conductUtil = require('../../../../vue-components/vc-tree/src/utils/conductUtil.cjs');
var index$1 = require('../../../../hooks/use-state/index.cjs');
var util = require('../../../../vue-components/vc-tree/src/util.cjs');
var legacyUtil = require('../../../../vue-components/vc-table/src/utils/legacyUtil.cjs');

const SELECTION_COLUMN = {};
const SELECTION_ALL = "SELECT_ALL";
const SELECTION_INVERT = "SELECT_INVERT";
const SELECTION_NONE = "SELECT_NONE";
const EMPTY_LIST = [];
function flattenData(childrenColumnName, data) {
  let list = [];
  (data || []).forEach((record) => {
    list.push(record);
    if (record && typeof record === "object" && childrenColumnName in record && record[childrenColumnName]) {
      list = [...list, ...flattenData(childrenColumnName, record[childrenColumnName])];
    }
  });
  return list;
}
function useSelection(rowSelectionRef, configRef) {
  const mergedRowSelection = vue.computed(() => {
    const temp = rowSelectionRef.value || {};
    const {
      checkStrictly = true
    } = temp;
    return {
      ...temp,
      checkStrictly
    };
  });
  const [mergedSelectedKeys, setMergedSelectedKeys] = index.useMergedState(mergedRowSelection.value.selectedRowKeys || mergedRowSelection.value.defaultSelectedRowKeys || EMPTY_LIST, {
    value: vue.computed(() => mergedRowSelection.value.selectedRowKeys)
  });
  const preserveRecordsRef = vue.shallowRef(/* @__PURE__ */ new Map());
  const updatePreserveRecordsCache = (keys) => {
    if (mergedRowSelection.value.preserveSelectedRowKeys) {
      const newCache = /* @__PURE__ */ new Map();
      keys.forEach((key) => {
        let record = configRef.getRecordByKey(key);
        if (!record && preserveRecordsRef.value.has(key))
          record = preserveRecordsRef.value.get(key);
        newCache.set(key, record);
      });
      preserveRecordsRef.value = newCache;
    }
  };
  vue.watchEffect(() => {
    updatePreserveRecordsCache(mergedSelectedKeys.value);
  });
  const keyEntities = vue.computed(() => mergedRowSelection.value.checkStrictly ? null : treeUtil.convertDataToEntities(configRef.data.value, {
    externalGetKey: configRef.getRowKey.value,
    childrenPropName: configRef.childrenColumnName.value
  }).keyEntities);
  const flattedData = vue.computed(() => flattenData(configRef.childrenColumnName.value, configRef.pageData.value));
  const checkboxPropsMap = vue.computed(() => {
    const map = /* @__PURE__ */ new Map();
    const getRowKey = configRef.getRowKey.value;
    const getCheckboxProps = mergedRowSelection.value.getCheckboxProps;
    flattedData.value.forEach((record, index) => {
      const key = getRowKey(record, index);
      const checkboxProps = (getCheckboxProps ? getCheckboxProps(record) : null) || {};
      map.set(key, checkboxProps);
      if (process.env.NODE_ENV !== "production" && ("checked" in checkboxProps || "defaultChecked" in checkboxProps)) {
        log.devWarning(false, "Table", "Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.");
      }
    });
    return map;
  });
  const {
    maxLevel,
    levelEntities
  } = useMaxLevel.default(keyEntities);
  const isCheckboxDisabled = (r) => {
    var _a;
    return !!((_a = checkboxPropsMap.value.get(configRef.getRowKey.value(r))) == null ? void 0 : _a.disabled);
  };
  const selectKeysState = vue.computed(() => {
    if (mergedRowSelection.value.checkStrictly)
      return [mergedSelectedKeys.value || [], []];
    const {
      checkedKeys,
      halfCheckedKeys
    } = conductUtil.conductCheck(mergedSelectedKeys.value, true, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled);
    return [checkedKeys || [], halfCheckedKeys];
  });
  const derivedSelectedKeys = vue.computed(() => selectKeysState.value[0]);
  const derivedHalfSelectedKeys = vue.computed(() => selectKeysState.value[1]);
  const derivedSelectedKeySet = vue.computed(() => {
    const keys = mergedRowSelection.value.type === "radio" ? derivedSelectedKeys.value.slice(0, 1) : derivedSelectedKeys.value;
    return new Set(keys);
  });
  const derivedHalfSelectedKeySet = vue.computed(() => mergedRowSelection.value.type === "radio" ? /* @__PURE__ */ new Set() : new Set(derivedHalfSelectedKeys.value));
  const [lastSelectedKey, setLastSelectedKey] = index$1.useState(null);
  const setSelectedKeys = (keys) => {
    let availableKeys;
    let records;
    updatePreserveRecordsCache(keys);
    const {
      preserveSelectedRowKeys,
      onChange: onSelectionChange
    } = mergedRowSelection.value;
    const {
      getRecordByKey
    } = configRef;
    if (preserveSelectedRowKeys) {
      availableKeys = keys;
      records = keys.map((key) => preserveRecordsRef.value.get(key));
    } else {
      availableKeys = [];
      records = [];
      keys.forEach((key) => {
        const record = getRecordByKey(key);
        if (record !== void 0) {
          availableKeys.push(key);
          records.push(record);
        }
      });
    }
    setMergedSelectedKeys(availableKeys);
    onSelectionChange == null ? void 0 : onSelectionChange(availableKeys, records);
  };
  const triggerSingleSelection = (key, selected, keys, event) => {
    const {
      onSelect
    } = mergedRowSelection.value;
    const {
      getRecordByKey
    } = configRef || {};
    if (onSelect) {
      const rows = keys.map((k) => getRecordByKey(k));
      onSelect(getRecordByKey(key), selected, rows, event);
    }
    setSelectedKeys(keys);
  };
  const mergedSelections = vue.computed(() => {
    const {
      onSelectInvert,
      onSelectNone,
      selections,
      hideSelectAll
    } = mergedRowSelection.value;
    const {
      data,
      pageData,
      getRowKey,
      locale: tableLocale
    } = configRef;
    if (!selections || hideSelectAll)
      return null;
    const selectionList = selections === true ? [SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE] : selections;
    return selectionList.map((selection) => {
      if (selection === SELECTION_ALL) {
        return {
          key: "all",
          text: tableLocale.value.selectionAll,
          onSelect() {
            setSelectedKeys(data.value.map((record, index) => getRowKey.value(record, index)).filter((key) => {
              const checkProps = checkboxPropsMap.value.get(key);
              return !(checkProps == null ? void 0 : checkProps.disabled) || derivedSelectedKeySet.value.has(key);
            }));
          }
        };
      }
      if (selection === SELECTION_INVERT) {
        return {
          key: "invert",
          text: tableLocale.value.selectInvert,
          onSelect() {
            const keySet = new Set(derivedSelectedKeySet.value);
            pageData.value.forEach((record, index) => {
              const key = getRowKey.value(record, index);
              const checkProps = checkboxPropsMap.value.get(key);
              if (!(checkProps == null ? void 0 : checkProps.disabled)) {
                if (keySet.has(key))
                  keySet.delete(key);
                else
                  keySet.add(key);
              }
            });
            const keys = Array.from(keySet);
            if (onSelectInvert) {
              log.devWarning(false, "Table", "`onSelectInvert` will be removed in future. Please use `onChange` instead.");
              onSelectInvert(keys);
            }
            setSelectedKeys(keys);
          }
        };
      }
      if (selection === SELECTION_NONE) {
        return {
          key: "none",
          text: tableLocale.value.selectNone,
          onSelect() {
            onSelectNone == null ? void 0 : onSelectNone();
            setSelectedKeys(Array.from(derivedSelectedKeySet.value).filter((key) => {
              const checkProps = checkboxPropsMap.value.get(key);
              return checkProps == null ? void 0 : checkProps.disabled;
            }));
          }
        };
      }
      return selection;
    });
  });
  const flattedDataLength = vue.computed(() => flattedData.value.length);
  const transformColumns = (columns) => {
    var _a;
    const {
      onSelectAll,
      onSelectMultiple,
      columnWidth: selectionColWidth,
      type: selectionType,
      fixed,
      renderCell: customizeRenderCell,
      hideSelectAll,
      checkStrictly
    } = mergedRowSelection.value;
    const {
      prefixCls,
      getRecordByKey,
      getRowKey,
      expandType,
      getPopupContainer
    } = configRef;
    if (!rowSelectionRef.value) {
      if (process.env.NODE_ENV !== "production") {
        log.devWarning(!columns.includes(SELECTION_COLUMN), "Table", "`rowSelection` is not config but `SELECTION_COLUMN` exists in the `columns`.");
      }
      return columns.filter((col) => col !== SELECTION_COLUMN);
    }
    let cloneColumns = columns.slice();
    const keySet = new Set(derivedSelectedKeySet.value);
    const recordKeys = flattedData.value.map(getRowKey.value).filter((key) => !checkboxPropsMap.value.get(key).disabled);
    const checkedCurrentAll = recordKeys.every((key) => keySet.has(key));
    const checkedCurrentSome = recordKeys.some((key) => keySet.has(key));
    const onSelectAllChange = () => {
      const changeKeys = [];
      if (checkedCurrentAll) {
        recordKeys.forEach((key) => {
          keySet.delete(key);
          changeKeys.push(key);
        });
      } else {
        recordKeys.forEach((key) => {
          if (!keySet.has(key)) {
            keySet.add(key);
            changeKeys.push(key);
          }
        });
      }
      const keys = Array.from(keySet);
      onSelectAll == null ? void 0 : onSelectAll(!checkedCurrentAll, keys.map((k) => getRecordByKey(k)), changeKeys.map((k) => getRecordByKey(k)));
      setSelectedKeys(keys);
    };
    let title;
    if (selectionType !== "radio") {
      let customizeSelections;
      if (mergedSelections.value) {
        const menu = vue.createVNode(index$2.Menu, {
          "getPopupContainer": getPopupContainer.value
        }, {
          default: () => [mergedSelections.value.map((selection, index) => {
            const {
              key,
              text,
              onSelect: onSelectionClick
            } = selection;
            return vue.createVNode(index$2.Menu.Item, {
              "key": key || index,
              "onClick": () => {
                onSelectionClick == null ? void 0 : onSelectionClick(recordKeys);
              }
            }, {
              default: () => [text]
            });
          })]
        });
        customizeSelections = vue.createVNode("div", {
          "class": `${prefixCls.value}-selection-extra`
        }, [vue.createVNode(index$3.Dropdown, {
          "overlay": menu,
          "getPopupContainer": getPopupContainer.value
        }, {
          default: () => [vue.createVNode("span", null, [vue.createVNode(iconsVue.DownOutlined, null, null)])]
        })]);
      }
      const allDisabledData = flattedData.value.map((record, index) => {
        const key = getRowKey.value(record, index);
        const checkboxProps = checkboxPropsMap.value.get(key) || {};
        return {
          checked: keySet.has(key),
          ...checkboxProps
        };
      }).filter(({
        disabled
      }) => disabled);
      const allDisabled = !!allDisabledData.length && allDisabledData.length === flattedDataLength.value;
      const allDisabledAndChecked = allDisabled && allDisabledData.every(({
        checked
      }) => checked);
      const allDisabledSomeChecked = allDisabled && allDisabledData.some(({
        checked
      }) => checked);
      title = !hideSelectAll && vue.createVNode("div", {
        "class": `${prefixCls.value}-selection`
      }, [vue.createVNode(index$4.Checkbox, {
        "checked": !allDisabled ? !!flattedDataLength.value && checkedCurrentAll : allDisabledAndChecked,
        "indeterminate": !allDisabled ? !checkedCurrentAll && checkedCurrentSome : !allDisabledAndChecked && allDisabledSomeChecked,
        "onChange": onSelectAllChange,
        "disabled": flattedDataLength.value === 0 || allDisabled,
        "aria-label": customizeSelections ? "Custom selection" : "Select all",
        "skipGroup": true
      }, null), customizeSelections]);
    }
    let renderCell;
    if (selectionType === "radio") {
      renderCell = ({
        record,
        index
      }) => {
        const key = getRowKey.value(record, index);
        const checked = keySet.has(key);
        return {
          node: vue.createVNode(index$5.Radio, {
            ...checkboxPropsMap.value.get(key),
            "checked": checked,
            "onClick": (e) => e.stopPropagation(),
            "onChange": (event) => {
              if (!keySet.has(key))
                triggerSingleSelection(key, true, [key], event.nativeEvent);
            }
          }, null),
          checked
        };
      };
    } else {
      renderCell = ({
        record,
        index
      }) => {
        var _a2;
        const key = getRowKey.value(record, index);
        const checked = keySet.has(key);
        const indeterminate = derivedHalfSelectedKeySet.value.has(key);
        const checkboxProps = checkboxPropsMap.value.get(key);
        let mergedIndeterminate;
        if (expandType.value === "nest") {
          mergedIndeterminate = indeterminate;
          log.devWarning(typeof (checkboxProps == null ? void 0 : checkboxProps.indeterminate) !== "boolean", "Table", "set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.");
        } else {
          mergedIndeterminate = (_a2 = checkboxProps == null ? void 0 : checkboxProps.indeterminate) != null ? _a2 : indeterminate;
        }
        return {
          node: vue.createVNode(index$4.Checkbox, {
            ...checkboxProps,
            "indeterminate": mergedIndeterminate,
            "checked": checked,
            "skipGroup": true,
            "onClick": (e) => e.stopPropagation(),
            "onChange": ({
              nativeEvent
            }) => {
              const {
                shiftKey
              } = nativeEvent;
              let startIndex = -1;
              let endIndex = -1;
              if (shiftKey && checkStrictly) {
                const pointKeys = /* @__PURE__ */ new Set([lastSelectedKey.value, key]);
                recordKeys.some((recordKey, recordIndex) => {
                  if (pointKeys.has(recordKey)) {
                    if (startIndex === -1) {
                      startIndex = recordIndex;
                    } else {
                      endIndex = recordIndex;
                      return true;
                    }
                  }
                  return false;
                });
              }
              if (endIndex !== -1 && startIndex !== endIndex && checkStrictly) {
                const rangeKeys = recordKeys.slice(startIndex, endIndex + 1);
                const changedKeys = [];
                if (checked) {
                  rangeKeys.forEach((recordKey) => {
                    if (keySet.has(recordKey)) {
                      changedKeys.push(recordKey);
                      keySet.delete(recordKey);
                    }
                  });
                } else {
                  rangeKeys.forEach((recordKey) => {
                    if (!keySet.has(recordKey)) {
                      changedKeys.push(recordKey);
                      keySet.add(recordKey);
                    }
                  });
                }
                const keys = Array.from(keySet);
                onSelectMultiple == null ? void 0 : onSelectMultiple(!checked, keys.map((recordKey) => getRecordByKey(recordKey)), changedKeys.map((recordKey) => getRecordByKey(recordKey)));
                setSelectedKeys(keys);
              } else {
                const originCheckedKeys = derivedSelectedKeys.value;
                if (checkStrictly) {
                  const checkedKeys = checked ? util.arrDel(originCheckedKeys, key) : util.arrAdd(originCheckedKeys, key);
                  triggerSingleSelection(key, !checked, checkedKeys, nativeEvent);
                } else {
                  const result = conductUtil.conductCheck([...originCheckedKeys, key], true, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled);
                  const {
                    checkedKeys,
                    halfCheckedKeys
                  } = result;
                  let nextCheckedKeys = checkedKeys;
                  if (checked) {
                    const tempKeySet = new Set(checkedKeys);
                    tempKeySet.delete(key);
                    nextCheckedKeys = conductUtil.conductCheck(Array.from(tempKeySet), {
                      checked: false,
                      halfCheckedKeys
                    }, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled).checkedKeys;
                  }
                  triggerSingleSelection(key, !checked, nextCheckedKeys, nativeEvent);
                }
              }
              setLastSelectedKey(key);
            }
          }, null),
          checked
        };
      };
    }
    const renderSelectionCell = ({
      record,
      index
    }) => {
      const {
        node,
        checked
      } = renderCell({
        record,
        index
      });
      if (customizeRenderCell)
        return customizeRenderCell(checked, record, index, node);
      return node;
    };
    if (!cloneColumns.includes(SELECTION_COLUMN)) {
      if (cloneColumns.findIndex((col) => {
        var _a2;
        return ((_a2 = col[legacyUtil.INTERNAL_COL_DEFINE]) == null ? void 0 : _a2.columnType) === "EXPAND_COLUMN";
      }) === 0) {
        const [expandColumn, ...restColumns] = cloneColumns;
        cloneColumns = [expandColumn, SELECTION_COLUMN, ...restColumns];
      } else {
        cloneColumns = [SELECTION_COLUMN, ...cloneColumns];
      }
    }
    const selectionColumnIndex = cloneColumns.indexOf(SELECTION_COLUMN);
    if (process.env.NODE_ENV !== "production" && cloneColumns.filter((col) => col === SELECTION_COLUMN).length > 1)
      log.devWarning(false, "Table", "Multiple `SELECTION_COLUMN` exist in `columns`.");
    cloneColumns = cloneColumns.filter((column, index) => column !== SELECTION_COLUMN || index === selectionColumnIndex);
    const prevCol = cloneColumns[selectionColumnIndex - 1];
    const nextCol = cloneColumns[selectionColumnIndex + 1];
    let mergedFixed = fixed;
    if (mergedFixed === void 0) {
      if ((nextCol == null ? void 0 : nextCol.fixed) !== void 0)
        mergedFixed = nextCol.fixed;
      else if ((prevCol == null ? void 0 : prevCol.fixed) !== void 0)
        mergedFixed = prevCol.fixed;
    }
    if (mergedFixed && prevCol && ((_a = prevCol[legacyUtil.INTERNAL_COL_DEFINE]) == null ? void 0 : _a.columnType) === "EXPAND_COLUMN" && prevCol.fixed === void 0)
      prevCol.fixed = mergedFixed;
    const selectionColumn = {
      fixed: mergedFixed,
      width: selectionColWidth,
      className: `${prefixCls.value}-selection-column`,
      title: mergedRowSelection.value.columnTitle || title,
      customRender: renderSelectionCell,
      [legacyUtil.INTERNAL_COL_DEFINE]: {
        class: `${prefixCls.value}-selection-col`
      }
    };
    return cloneColumns.map((col) => col === SELECTION_COLUMN ? selectionColumn : col);
  };
  return [transformColumns, derivedSelectedKeySet];
}

exports.SELECTION_ALL = SELECTION_ALL;
exports.SELECTION_COLUMN = SELECTION_COLUMN;
exports.SELECTION_INVERT = SELECTION_INVERT;
exports.SELECTION_NONE = SELECTION_NONE;
exports.default = useSelection;
//# sourceMappingURL=useSelection.cjs.map
