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 __rest = this && this.__rest || function (s, e) {
  var t = {};

  for (var p in s) {
    if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  }

  if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
    if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  }
  return t;
};

import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import * as React from 'react';
import { useCallback, useMemo } from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { List } from 'react-virtualized';
import useStaticCallback from "../../hooks/useStaticCallback";
import createScrollbar from "../scrollbar/createScrollbar";
import Icon from "../icon";
import "./style/sort-list.css";
import useDataValue from "../../hooks/useDataValue";
import FieldItem from "../field-item";
var prefixCls = 'dmc-sort-list';
var itemCls = prefixCls + "-item";
var handleCls = itemCls + "-handle";
var labelCls = itemCls + "-label";
var ActionEnum;

(function (ActionEnum) {
  ActionEnum["Up"] = "up";
  ActionEnum["Down"] = "down";
  ActionEnum["Del"] = "del";
})(ActionEnum || (ActionEnum = {}));

var plainRowRenderer = function plainRowRenderer(index, value, item, handleClose) {
  return _jsx("div", __assign({
    className: prefixCls + "-plain-row-wrap"
  }, {
    children: _jsx(FieldItem, {
      type: typeof item === 'string' ? 'text' : item.type || 'text',
      name: value,
      checked: true,
      onClose: handleClose,
      dataValue: ActionEnum.Del + "-" + index
    }, void 0)
  }), void 0);
};

var arrayMove = function arrayMove(list, startIndex, endIndex) {
  var result = Array.from(list);
  var removed = result.splice(startIndex, 1)[0];
  result.splice(endIndex, 0, removed);
  return result;
};

var SortList = function SortList(props) {
  var _a;

  var _b = props,
      type = _b.type,
      mode = _b.mode,
      listHeight = _b.listHeight,
      listWidth = _b.listWidth,
      rowHeight = _b.rowHeight,
      list = _b.list,
      defaultList = _b.defaultList,
      valueKey = _b.valueKey,
      labelKey = _b.labelKey,
      onChange = _b.onChange,
      renderItem = _b.renderItem,
      disabled = _b.disabled,
      visibleUpDown = _b.visibleUpDown,
      removable = _b.removable,
      useVirtual = _b.useVirtual,
      restProps = __rest(_b, ["type", "mode", "listHeight", "listWidth", "rowHeight", "list", "defaultList", "valueKey", "labelKey", "onChange", "renderItem", "disabled", "visibleUpDown", "removable", "useVirtual"]);

  var _c = React.useState(defaultList),
      unControlVal = _c[0],
      setUnControlVal = _c[1];

  var _d = React.useState(false),
      isDraging = _d[0],
      setDraging = _d[1];

  var isControl = ('list' in props);
  var val = isControl ? list : unControlVal;
  var isObj = typeof val[0] !== 'string';
  var psRef = React.useRef();
  var listRef = React.useRef(null);
  React.useEffect(function () {
    if (listRef.current) {
      var _a = createScrollbar(listRef.current, type),
          ps = _a[0],
          destroy_1 = _a[1];

      psRef.current = ps;
      return function () {
        destroy_1();
        psRef.current = undefined;
      };
    }
  }, [type]);
  React.useEffect(function () {
    var _a;

    (_a = psRef.current) === null || _a === void 0 ? void 0 : _a.update();
  });
  var onDragEnd = useStaticCallback(function (result) {
    if (!result.destination || result.destination.index === result.source.index) {
      return;
    }

    var list = arrayMove(val, result.source.index, result.destination.index);
    !isControl && setUnControlVal(list);
    setDraging(false);
    onChange && onChange(list, result);
  });
  var onDragStart = React.useCallback(function () {
    setDraging(true);
  }, []);
  var clickItemActionIcon = useDataValue(function (value) {
    var _a = value.split('-'),
        action = _a[0],
        indexStr = _a[1];

    var cIndex = parseInt(indexStr);
    var list = [];

    if (action === ActionEnum.Up) {
      if (cIndex === 0) return;
      list = arrayMove(val, cIndex, 0);
    } else if (action === ActionEnum.Down) {
      if (cIndex === val.length - 1) return;
      list = arrayMove(val, cIndex, val.length - 1);
    } else if (action === ActionEnum.Del) {
      list = val.filter(function (_, index) {
        return index !== cIndex;
      });
    }

    !isControl && setUnControlVal(list);
    onChange && onChange(list);
  });
  var getRowRender = useCallback(function (_a) {
    var _b;

    var index = _a.index,
        style = _a.style;
    var item = val[index];
    var key = JSON.stringify(isObj ? item[valueKey] : item);
    var cls = classNames(itemCls, (_b = {}, _b[itemCls + "-draging"] = isDraging, _b));
    return _jsx(Draggable, __assign({
      draggableId: key,
      index: index,
      isDragDisabled: disabled
    }, {
      children: function children(provided) {
        // combine virtual inline style and drag inline style
        var _a = provided.draggableProps,
            _b = _a.style,
            dragStyle = _b === void 0 ? {} : _b,
            otherDragProps = __rest(_a, ["style"]);

        var styleProps = {
          style: dragStyle
        };

        if (style) {
          styleProps.style = __assign(__assign({}, styleProps.style), style);
        }

        var val = isObj ? item[labelKey] : item;
        return _jsx(_Fragment, {
          children: renderItem ? renderItem(provided, item, index, isDraging, styleProps.style) : _jsxs("div", __assign({
            className: cls,
            ref: provided.innerRef
          }, otherDragProps, styleProps, {
            children: [!disabled && _jsx(Icon, __assign({
              icon: "drag-handle",
              className: handleCls
            }, provided.dragHandleProps), void 0), mode === 'plain' ? plainRowRenderer(index, val, item, clickItemActionIcon) : _jsx("div", __assign({
              className: labelCls
            }, {
              children: val
            }), void 0), mode === 'normal' && !!visibleUpDown && _jsx(Icon, {
              icon: "vertical-align-top",
              className: itemCls + "-action",
              onClick: clickItemActionIcon,
              "data-value": ActionEnum.Up + "-" + index
            }, void 0), mode === 'normal' && !!visibleUpDown && _jsx(Icon, {
              icon: "vertical-align-bottom",
              className: itemCls + "-action",
              onClick: clickItemActionIcon,
              "data-value": ActionEnum.Down + "-" + index
            }, void 0), mode === 'normal' && !!removable && _jsx(Icon, {
              icon: "close",
              className: itemCls + "-action",
              onClick: clickItemActionIcon,
              "data-value": ActionEnum.Del + "-" + index
            }, void 0)]
          }), void 0)
        }, void 0);
      }
    }), key);
  }, [clickItemActionIcon, disabled, isDraging, isObj, labelKey, mode, removable, renderItem, val, valueKey, visibleUpDown]);
  var otherProps = useMemo(function () {
    if (useVirtual) {
      return {
        mode: 'virtual',
        renderClone: function renderClone(provided, snapshot, rubric) {
          var _a;

          var _index = rubric.source.index;
          var item = val[_index];
          var cls = classNames(itemCls, (_a = {}, _a[itemCls + "-draging"] = snapshot.isDragging, _a));
          var content = isObj ? item[labelKey] : item;
          return _jsx("div", __assign({}, provided.draggableProps, provided.dragHandleProps, {
            ref: provided.innerRef,
            className: cls
          }, {
            children: renderItem ? renderItem(provided, item, _index, snapshot.isDragging) : mode === 'plain' ? plainRowRenderer(_index, content, item) : _jsx("div", __assign({
              className: labelCls
            }, {
              children: content
            }), void 0)
          }), void 0);
        }
      };
    } else {
      return {};
    }
  }, [isObj, labelKey, mode, renderItem, useVirtual, val]);
  return _jsx("div", __assign({}, restProps, {
    className: classNames(prefixCls, (_a = {}, _a[prefixCls + "-" + type] = type, _a[prefixCls + "-" + mode] = mode === 'plain', _a))
  }, {
    children: _jsx(DragDropContext, __assign({
      onDragEnd: onDragEnd,
      onDragStart: onDragStart
    }, {
      children: _jsx(Droppable, __assign({
        droppableId: prefixCls
      }, otherProps, {
        children: function children(provided) {
          return useVirtual ? _jsx(List, {
            height: listHeight || 300,
            width: listWidth || 200,
            rowCount: val.length,
            rowHeight: rowHeight,
            ref: function ref(_ref) {
              if (_ref) {
                // eslint-disable-next-line react/no-find-dom-node
                var dom = ReactDOM.findDOMNode(_ref);

                if (dom instanceof HTMLElement) {
                  provided.innerRef(dom);
                  listRef.current = dom;
                }
              }
            },
            rowRenderer: getRowRender
          }, void 0) : _jsxs("div", __assign({
            ref: provided.innerRef
          }, provided.droppableProps, {
            children: [val.map(function (_item, index) {
              return getRowRender({
                index: index
              });
            }), provided.placeholder]
          }), void 0);
        }
      }), void 0)
    }), void 0)
  }), void 0);
};

SortList.displayName = 'SortList';
var defaultProps = {
  mode: 'normal',
  rowHeight: 30,
  // list: [] as SortListItemType[],
  defaultList: [],
  valueKey: 'value',
  labelKey: 'label',
  disabled: false,
  useVirtual: false
};
SortList.defaultProps = defaultProps;
export default SortList;
var SortListMemo = /*#__PURE__*/React.memo(SortList);
SortListMemo.displayName = 'SortListMemo';
export { SortListMemo };

