import _regeneratorRuntime from "@babel/runtime/regenerator";
var _excluded = ["multiple", "checkbox", "checkStrictly", "arrowAutoShow", "expand", "expandPredecessors", "bar", "treeAttribute", "buttonAddAttribute", "buttonDelAttribute", "keyword", "keywordAttribute", "selected", "selectedAutoClear", "list", "getChildren", "onChange", "onClick", "onClickLeaf", "onData", "params"];

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

// require PrototypeArray.js(flattenTree)
import React, { forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
import usePrevious from './../usePrevious';
import Instance from './instance.js';
var Tree = forwardRef(function (_ref, ref) {
  var _ref$multiple = _ref.multiple,
      multiple = _ref$multiple === void 0 ? false : _ref$multiple,
      _ref$checkbox = _ref.checkbox,
      checkbox = _ref$checkbox === void 0 ? true : _ref$checkbox,
      _ref$checkStrictly = _ref.checkStrictly,
      checkStrictly = _ref$checkStrictly === void 0 ? true : _ref$checkStrictly,
      _ref$arrowAutoShow = _ref.arrowAutoShow,
      arrowAutoShow = _ref$arrowAutoShow === void 0 ? false : _ref$arrowAutoShow,
      _ref$expand = _ref.expand,
      expand = _ref$expand === void 0 ? false : _ref$expand,
      _ref$expandPredecesso = _ref.expandPredecessors,
      expandPredecessors = _ref$expandPredecesso === void 0 ? true : _ref$expandPredecesso,
      bar = _ref.bar,
      _ref$treeAttribute = _ref.treeAttribute,
      treeAttribute = _ref$treeAttribute === void 0 ? {} : _ref$treeAttribute,
      _ref$buttonAddAttribu = _ref.buttonAddAttribute,
      buttonAddAttribute = _ref$buttonAddAttribu === void 0 ? {} : _ref$buttonAddAttribu,
      _ref$buttonDelAttribu = _ref.buttonDelAttribute,
      buttonDelAttribute = _ref$buttonDelAttribu === void 0 ? {} : _ref$buttonDelAttribu,
      _ref$keyword = _ref.keyword,
      keyword = _ref$keyword === void 0 ? '' : _ref$keyword,
      _ref$keywordAttribute = _ref.keywordAttribute,
      keywordAttribute = _ref$keywordAttribute === void 0 ? {
    pinyin: true
  } : _ref$keywordAttribute,
      _ref$selected = _ref.selected,
      selected = _ref$selected === void 0 ? [] : _ref$selected,
      _ref$selectedAutoClea = _ref.selectedAutoClear,
      selectedAutoClear = _ref$selectedAutoClea === void 0 ? false : _ref$selectedAutoClea,
      _ref$list = _ref.list,
      list = _ref$list === void 0 ? [] : _ref$list,
      getChildren = _ref.getChildren,
      onChange = _ref.onChange,
      onClick = _ref.onClick,
      onClickLeaf = _ref.onClickLeaf,
      onData = _ref.onData,
      _ref$params = _ref.params,
      params = _ref$params === void 0 ? {} : _ref$params,
      others = _objectWithoutPropertiesLoose(_ref, _excluded);

  var refEl = useRef(null);
  useImperativeHandle(ref, function () {
    return refEl.current;
  });
  var instance = useRef(null); // 是否是深层数据结构

  var isChildrenData = useRef(false); // 初始化树结构

  useEffect(function () {
    if (instance.current) return; // 更新数据

    var data = convertData(list);
    var elTree = refEl.current.querySelector('ul');
    console.log('初始化, 是否多选:' + multiple);
    instance.current = new Instance(elTree, _extends({
      data: data,
      selectedAutoClear: selectedAutoClear,
      // 关键字
      keyword: keyword,
      keywordPinyin: keywordAttribute.pinyin,
      keywordClass: keywordAttribute.className,
      keywordCss: keywordAttribute.css,
      expand: expand,
      expandPredecessors: expandPredecessors,
      multiple: multiple,
      checkbox: checkbox,
      checkStrictly: checkStrictly,
      arrowAutoShow: arrowAutoShow,
      bar: bar,
      buttonAddClass: buttonAddAttribute.className,
      onClickAdd: buttonAddAttribute.onClick,
      buttonDelClass: buttonDelAttribute.className,
      onClickDel: buttonDelAttribute.onClick,
      onClick: handleClick,
      onChange: handleChange,
      onData: onData
    }, params || {}));
    refEl.current.instance = instance; // 渲染数据

    handleRender();
  }, []); // eslint-disable-line
  // 比较变化

  var prevSelected = usePrevious(selected); // 比较选中是否不同, 不同更新树

  useEffect(function () {
    if (!instance.current || !prevSelected || !selected || !Array.isArray(prevSelected)) return;
    var delIds = []; // 删除项

    var addOptions = []; // 新增项
    // 上次的对象

    var prevSelectedMap = {};

    for (var _iterator = _createForOfIteratorHelperLoose(prevSelected), _step; !(_step = _iterator()).done;) {
      var item = _step.value;
      prevSelectedMap[item.id] = item;
    } // 上次的对象


    var selectedMap = {};

    for (var _iterator2 = _createForOfIteratorHelperLoose(selected), _step2; !(_step2 = _iterator2()).done;) {
      var _item = _step2.value;
      selectedMap[_item.id] = _item;
    } // 此次比上次多的为新增


    for (var id in selectedMap) {
      // 新增项
      if (!prevSelectedMap[id]) {
        addOptions.push(selectedMap[id]);
      }
    } // 此次比上次少的为删除


    for (var _id in prevSelectedMap) {
      // 新增项
      if (!selectedMap[_id]) {
        delIds.push(_id);
      }
    } // 更新删除项


    for (var _i = 0, _delIds = delIds; _i < _delIds.length; _i++) {
      var _id2 = _delIds[_i];
      instance.current.removeSelected(_id2);
    } // 更新新增项


    for (var _i2 = 0, _addOptions = addOptions; _i2 < _addOptions.length; _i2++) {
      var option = _addOptions[_i2];
      instance.current.addSelected(option);
    }
  }, [selected]); // eslint-disable-line
  // 展开与收缩

  useEffect(function () {
    handleExpand();
  }, [expand]); // 数据更新

  useEffect(function () {
    if (!instance.current) return;
    handleRender();
  }, [list]); // eslint-disable-line
  // 选中栏

  useEffect(function () {
    handleBar();
  }, [bar]); // eslint-disable-line
  // 关键字过滤

  useEffect(function () {
    handleKeyword();
  }, [keyword]); // eslint-disable-line
  // 更新句柄, 防止synchronization模式, 每次组件在render的时候都生成上次render的state、function、effects

  if (instance.current) {
    instance.current.params.onClick = handleClick;
    instance.current.params.onChange = handleChange;
    instance.current.params.onData = onData;
  } // 渲染


  function handleRender() {
    if (!instance.current) return;

    if (list && list.length) {
      var data = Object.clone(list);
      isChildrenData.current = JSON.stringify(data).indexOf('"children"') !== -1;

      if (isChildrenData.current) {
        data = data.flattenTree();
      } // 开始渲染


      instance.current.setData(data);
      instance.current.update(); // 选中选中项

      handleSelected(); // 更新展开状态

      handleExpand(); // 如果有关键字, 搜索关键字

      handleKeyword();
    } else {
      instance.current.setData([]);
      instance.current.update();
    }
  } // 更新展开状态


  function handleExpand() {
    instance.current.params.expand = expand;
    instance.current.expand();
  } // 关键字查询


  function handleKeyword() {
    if (typeof keyword !== 'string' || !instance.current) return;

    if (keywordAttribute.className) {
      instance.current.params.keywordClass = keywordAttribute.className;
    }

    if (keywordAttribute.css) {
      instance.current.params.keywordCss = keywordAttribute.css;
    }

    instance.current.search(keyword);
  } // 选中选中项


  function handleSelected() {
    if (selected && selected.length) {
      for (var _iterator3 = _createForOfIteratorHelperLoose(selected), _step3; !(_step3 = _iterator3()).done;) {
        var item = _step3.value;
        instance.current.addSelected(item);
      }
    } else {
      instance.current.removeAllSelected();
    }
  } // 当bar更新时, 选中项放到bar上


  function handleBar() {
    if (!bar || !instance.current) return;
    instance.current.params.bar = bar;
    instance.current.updateBar();
  } // 选中项


  function handleChange(s) {
    if (refEl.current) s.target = refEl.current;

    if (onChange) {
      var value = [];

      for (var id in s.selected) {
        value.push(s.selected[id].name);
      }

      onChange(s, value.join(','), Object.values(s.selected));
    }
  } // 判断是否选中


  function isSelected(id) {
    if (!Array.isArray(selected) || !id) return false;

    for (var _iterator4 = _createForOfIteratorHelperLoose(selected), _step4; !(_step4 = _iterator4()).done;) {
      var item = _step4.value;
      if (item.id === id) return true;
    }

    return false;
  } // 转换传入的数据为tree实例所需数据


  function convertData(list) {
    var data = Object.clone(list);
    isChildrenData.current = JSON.stringify(data).indexOf('"children"') !== -1;

    if (isChildrenData.current) {
      data = data.flattenTree();
    }

    return data;
  } // 点击


  function handleClick(s) {
    if (!s.targetLine) return;
    if (refEl.current) s.target = refEl.current;
    var data = convertData(list); // item

    var id = s.targetLine.getAttribute('data-id');
    var item = s.targetLine.getAttribute('data-node');

    if (item && typeof item === 'string') {
      try {
        item = JSON.parse(decodeURIComponent(decodeURIComponent(item)));
      } catch (error) {
        // 从list中拿此条数据有问题, 因为list是不变的, 而动态渲染的过程就是不断地向data中注入子数据
        item = data.getFlattenTreeNode(id);
      }
    } // isActived


    var isActived = isSelected(id) ? true : false; // childrenCount

    var childrenCount = 0;
    var ul = s.targetLine.nextElementSibling;

    if (ul && ul.tagName === 'UL') {
      childrenCount = ul.children.length;
    } // isExpand


    var isExpand = s.targetLine.classList.contains('expand'); // 点击回调

    if (onClick) onClick(s, item.name, item, isActived, isExpand, childrenCount);
    if (s.isLeaf && onClickLeaf) onClickLeaf(s, item.name, item, isActived);

    if (getChildren) {
      addChildren(s, item, isActived, isExpand, childrenCount);
    }
  } // 异步加载的方法, 点击Title, 去请求数据, 将数据塞到指定节点下


  function addChildren(_x, _x2, _x3, _x4, _x5) {
    return _addChildren.apply(this, arguments);
  }

  function _addChildren() {
    _addChildren = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(s, item, isActived, isExpand, childrenCount) {
      var ul, leaf;
      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              if (!(!item || !item.id || !isExpand || s.targetLine.getAttribute('data-childrenloaded'))) {
                _context.next = 2;
                break;
              }

              return _context.abrupt("return");

            case 2:
              ul = s.targetLine.nextElementSibling;
              _context.next = 5;
              return getChildren(item.id);

            case 5:
              leaf = _context.sent;

              if (!(leaf instanceof Array === false)) {
                _context.next = 8;
                break;
              }

              return _context.abrupt("return");

            case 8:
              // 修改原数据
              if (isChildrenData.current) {
                // 修改children数据, 并标识异步加载完成
                list.setDeepTreeNodeProp(item.id, {
                  children: leaf,
                  childrenLoaded: true
                });
              } else {
                // 修改扁平数据
                list.push.apply(list, leaf); // 标识异步加载完成

                list.setFlattenTreeNodeProp(item.id, {
                  childrenLoaded: true
                });
              } // 格式化数据


              leaf = convertData(leaf); // 添加数据, 并标识异步加载完成

              instance.current.addData(leaf, item.id, ul);
              if (s.targetLine) s.targetLine.setAttribute('data-childrenloaded', '1');

            case 12:
            case "end":
              return _context.stop();
          }
        }
      }, _callee);
    }));
    return _addChildren.apply(this, arguments);
  }

  return /*#__PURE__*/React.createElement("div", _extends({
    ref: refEl
  }, others, {
    className: "tree-box" + (checkStrictly ? ' tree-strictly' : '') + (others.className ? ' ' + others.className : '')
  }), /*#__PURE__*/React.createElement("ul", _extends({}, treeAttribute, {
    className: "tree" + (multiple ? '' : ' tree-type-radio') + (treeAttribute.className ? ' ' + treeAttribute.className : '')
  })));
});
export default Tree;