import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { defineComponent, computed, ref, watch, unref, shallowRef, triggerRef, resolveComponent, openBlock, createElementBlock, normalizeClass, createVNode, withCtx, normalizeStyle, Fragment, withDirectives, withModifiers, vShow, createElementVNode, toDisplayString, createBlock } from 'vue';
import { debounce } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import { useTheme } from '../_theme/useTheme';
import { useArrayModel, useNormalModel } from '../_util/use/useModel';
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '../_util/constants';
import useFormAdaptor from '../_util/use/useFormAdaptor';
import Popper from '../popper';
import SelectTrigger from '../select-trigger';
import Tree from '../tree/tree';
import Scrollbar from '../scrollbar/scrollbar.js';
import { selectProps } from '../select/props';
import { treeProps } from '../tree/props';
import { useLocale } from '../config-provider/useLocale';
import { noop } from '../_util/utils';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('select-tree');

/** multiple 时，modelValue 的类型 */

const selectTreeProps = _objectSpread(_objectSpread(_objectSpread({}, selectProps), treeProps), {}, {
  modelValue: {
    type: [String, Number, Array]
  },
  showPath: {
    type: Boolean,
    default: false
  },
  emitPath: {
    type: Boolean,
    default: false
  }
});
const COMPONENT_NAME = 'FSelectTree';
var script = defineComponent({
  name: COMPONENT_NAME,
  components: {
    Popper,
    SelectTrigger,
    Tree,
    Scrollbar
  },
  props: selectTreeProps,
  emits: [UPDATE_MODEL_EVENT, CHANGE_EVENT, 'update:expandedKeys', 'removeTag', 'visibleChange', 'focus', 'blur', 'clear', 'filter'],
  setup(props, _ref) {
    let {
      emit,
      attrs
    } = _ref;
    useTheme();
    const {
      validate,
      isError,
      isFormDisabled
    } = useFormAdaptor({
      valueType: computed(() => props.multiple ? 'array' : 'string')
    });
    const isOpened = ref(false);

    // 与 props 中 modelValue 类型保持一致
    const [currentValue, updateCurrentValue] = props.multiple ? useArrayModel(props, emit) : useNormalModel(props, emit);
    const [currentExpandedKeys] = useNormalModel(props, emit, {
      prop: 'expandedKeys'
    });
    const filterText = ref('');
    const {
      t
    } = useLocale();
    const inputPlaceholder = computed(() => props.placeholder || t('select.placeholder'));
    const listEmptyText = computed(() => props.emptyText || t('select.emptyText'));
    const innerDisabled = computed(() => props.disabled || isFormDisabled.value);
    watch(isOpened, () => {
      emit('visibleChange', unref(isOpened));

      // trigger 在mounted 之后可能会改变
      if (isOpened.value && triggerDomRef.value) {
        triggerWidth.value = triggerDomRef.value.$el.offsetWidth;
      }
    });
    const handleChange = () => {
      emit(CHANGE_EVENT, currentValue.value);
      validate(CHANGE_EVENT);
    };
    const nodeList = shallowRef(new Map());
    const onChangeNodeList = data => {
      nodeList.value = data;
      triggerRef(nodeList);
    };
    const getCurrentValueByKeys = function () {
      var _nodeList$value$get;
      let keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
      if (props.multiple) {
        return keys.map(key => {
          if (props.emitPath) {
            const node = nodeList.value.get(key);
            return [...((node === null || node === void 0 ? void 0 : node.indexPath) || [key])];
          }
          return key;
        });
      }
      return props.emitPath ? [...(((_nodeList$value$get = nodeList.value.get(keys[0])) === null || _nodeList$value$get === void 0 ? void 0 : _nodeList$value$get.indexPath) || [])] : keys[0];
    };
    const treeSelectable = computed(() => !props.multiple);
    const treeCheckable = computed(() => props.multiple);
    const selectedKeys = computed(() => {
      if (!props.multiple) {
        if (props.emitPath && Array.isArray(currentValue.value)) {
          return [currentValue.value[currentValue.value.length - 1]];
        }
        return currentValue.value ? [currentValue.value] : [];
      }
      return [];
    });
    const checkedKeys = computed(() => {
      var _currentValue$value;
      if (props.multiple && (_currentValue$value = currentValue.value) !== null && _currentValue$value !== void 0 && _currentValue$value.length) {
        const keys = currentValue.value.map(item => props.emitPath && Array.isArray(item) ? item[item.length - 1] : item);
        return keys;
      }
      return [];
    });
    watch([() => props.checkStrictly, () => props.emitPath], () => {
      const value = props.multiple && props.cascade || props.emitPath ? [] : null;
      updateCurrentValue(value);
      handleChange();
    });
    const handleClear = () => {
      const value = props.multiple ? [] : null;
      if (props.multiple ? currentValue.value.length : currentValue.value !== null) {
        updateCurrentValue(value);
        handleChange();
      }
      emit('clear');
    };
    const handleSelect = data => {
      if (innerDisabled.value) {
        return;
      }
      filterText.value = '';
      if (!props.multiple) {
        isOpened.value = false;
      }
      updateCurrentValue(getCurrentValueByKeys(data.selectedKeys));
      handleChange();
    };
    const handleCheck = data => {
      if (innerDisabled.value) {
        return;
      }
      filterText.value = '';
      if (!props.multiple) {
        isOpened.value = false;
      }
      updateCurrentValue(getCurrentValueByKeys(data.checkedKeys));
      handleChange();
    };

    /** 节点目标值 */
    const targetValues = computed(() => {
      const values = props.multiple ? currentValue.value : [currentValue.value];
      if (props.emitPath) {
        // 获取选中节点
        return values.map(item => item[item.length - 1]); // TODO: TreeNodeKey 类型是否不应包含 number
      }
      return values;
    });
    const handleRemove = value => {
      if (!props.multiple) {
        return;
      }
      const findIndex = targetValues.value.indexOf(value);
      if (findIndex !== -1) {
        emit('removeTag', value);
        const values = [...targetValues.value];
        values.splice(findIndex, 1);
        updateCurrentValue(getCurrentValueByKeys(values));
        handleChange();
      }
    };
    const selectedOptions = computed(() => {
      const nodeListValue = nodeList.value;
      return targetValues.value.map(val => {
        const node = nodeListValue.get(val);
        if (!node) {
          return;
        }
        if (props.showPath) {
          var _node$indexPath;
          return _objectSpread(_objectSpread({}, node), {}, {
            label: (_node$indexPath = node.indexPath) === null || _node$indexPath === void 0 ? void 0 : _node$indexPath.map(item => {
              var _nodeListValue$get;
              return ((_nodeListValue$get = nodeListValue.get(item)) === null || _nodeListValue$get === void 0 ? void 0 : _nodeListValue$get.label) || item;
            }).join('/')
          });
        } else {
          return node;
        }
      }).filter(Boolean);
    });
    const focus = e => {
      emit('focus', e);
      validate('focus');
    };
    const blur = e => {
      if (isOpened.value) {
        isOpened.value = false;
      }
      emit('blur', e);
      validate('blur');
    };
    const handleFilterTextChange = val => {
      filterText.value = val;
      emit('filter', val);
    };
    const refTree = ref(null);
    watch(filterText, debounce(() => {
      refTree.value.filter(filterText.value);
    }, 300));
    const filterMethod = computed(() => {
      if (!props.filterable) {
        return noop;
      }
      if (props.filter) {
        return props.filter;
      }
      if (props.data.some(option => typeof option[props.labelField] !== 'string')) {
        console.warn(`[${COMPONENT_NAME}]：label 存在自定义渲染，需要传入 filter`);
        return () => false;
      }
      return (value, node) => {
        return node.label.indexOf(value) !== -1;
      };
    });
    const triggerDomRef = ref();
    const triggerWidth = ref(0);
    const dropdownStyle = computed(() => {
      const style = {};
      if (triggerWidth.value) {
        style['min-width'] = `${triggerWidth.value}px`;
      }
      return style;
    });
    return {
      prefixCls,
      isOpened,
      currentValue,
      currentExpandedKeys,
      handleRemove,
      handleClear,
      selectedOptions,
      focus,
      blur,
      handleFilterTextChange,
      treeSelectable,
      selectedKeys,
      treeCheckable,
      handleSelect,
      handleCheck,
      checkedKeys,
      refTree,
      filterMethod,
      triggerDomRef,
      dropdownStyle,
      onChangeNodeList,
      inputPlaceholder,
      listEmptyText,
      isError,
      attrs,
      innerDisabled,
      filterText
    };
  }
});

function render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_SelectTrigger = resolveComponent("SelectTrigger");
  const _component_Tree = resolveComponent("Tree");
  const _component_Scrollbar = resolveComponent("Scrollbar");
  const _component_Popper = resolveComponent("Popper");
  return openBlock(), createElementBlock("div", {
    class: normalizeClass(_ctx.prefixCls)
  }, [createVNode(_component_Popper, {
    modelValue: _ctx.isOpened,
    "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => _ctx.isOpened = $event),
    trigger: "click",
    placement: "bottom-start",
    popperClass: `${_ctx.prefixCls}-popper`,
    appendToContainer: _ctx.appendToContainer,
    getContainer: _ctx.getContainer,
    offset: 4,
    hideAfter: 0,
    disabled: _ctx.innerDisabled,
    lazy: false
  }, {
    trigger: withCtx(() => [createVNode(_component_SelectTrigger, {
      ref: "triggerDomRef",
      selectedOptions: _ctx.selectedOptions,
      disabled: _ctx.innerDisabled,
      clearable: _ctx.clearable,
      isOpened: _ctx.isOpened,
      multiple: _ctx.multiple,
      placeholder: _ctx.inputPlaceholder,
      filterable: _ctx.filterable,
      collapseTags: _ctx.collapseTags,
      collapseTagsLimit: _ctx.collapseTagsLimit,
      tagBordered: _ctx.tagBordered,
      class: normalizeClass([{
        'is-error': _ctx.isError
      }, _ctx.attrs.class]),
      style: normalizeStyle(_ctx.attrs.style),
      renderTag: _ctx.$slots.tag,
      onRemove: _ctx.handleRemove,
      onClear: _ctx.handleClear,
      onFocus: _ctx.focus,
      onBlur: _ctx.blur,
      onInput: _ctx.handleFilterTextChange
    }, null, 8 /* PROPS */, ["selectedOptions", "disabled", "clearable", "isOpened", "multiple", "placeholder", "filterable", "collapseTags", "collapseTagsLimit", "tagBordered", "class", "style", "renderTag", "onRemove", "onClear", "onFocus", "onBlur", "onInput"])]),
    default: withCtx(() => [_ctx.virtualList && !_ctx.inline ? (openBlock(), createElementBlock(Fragment, {
      key: 0
    }, [withDirectives(createVNode(_component_Tree, {
      ref: "refTree",
      expandedKeys: _ctx.currentExpandedKeys,
      "onUpdate:expandedKeys": _cache[0] || (_cache[0] = $event => _ctx.currentExpandedKeys = $event),
      selectedKeys: _ctx.selectedKeys,
      checkedKeys: _ctx.checkedKeys,
      data: _ctx.data,
      defaultExpandAll: _ctx.defaultExpandAll,
      accordion: _ctx.accordion,
      selectable: _ctx.treeSelectable,
      checkable: _ctx.treeCheckable,
      checkStrictly: _ctx.checkStrictly,
      cascade: _ctx.cascade,
      multiple: _ctx.multiple,
      childrenField: _ctx.childrenField,
      valueField: _ctx.valueField,
      labelField: _ctx.labelField,
      filterMethod: _ctx.filterMethod,
      inline: _ctx.inline,
      remote: _ctx.remote,
      loadData: _ctx.loadData,
      virtualList: "",
      style: normalizeStyle(_ctx.dropdownStyle),
      class: normalizeClass(`${_ctx.prefixCls}-dropdown is-max-height`),
      filterText: _ctx.filterText,
      filterTextHighlight: _ctx.filterTextHighlight,
      "onUpdate:nodeList": _ctx.onChangeNodeList,
      onSelect: _ctx.handleSelect,
      onCheck: _ctx.handleCheck,
      onMousedown: _cache[1] || (_cache[1] = withModifiers(() => {}, ["prevent"]))
    }, null, 8 /* PROPS */, ["expandedKeys", "selectedKeys", "checkedKeys", "data", "defaultExpandAll", "accordion", "selectable", "checkable", "checkStrictly", "cascade", "multiple", "childrenField", "valueField", "labelField", "filterMethod", "inline", "remote", "loadData", "style", "class", "filterText", "filterTextHighlight", "onUpdate:nodeList", "onSelect", "onCheck"]), [[vShow, _ctx.data.length]]), withDirectives(createElementVNode("div", {
      class: normalizeClass(`${_ctx.prefixCls}-null`),
      onMousedown: _cache[2] || (_cache[2] = withModifiers(() => {}, ["prevent"]))
    }, toDisplayString(_ctx.listEmptyText), 35 /* TEXT, CLASS, NEED_HYDRATION */), [[vShow, !_ctx.data.length]])], 64 /* STABLE_FRAGMENT */)) : (openBlock(), createBlock(_component_Scrollbar, {
      key: 1,
      containerStyle: _ctx.dropdownStyle,
      containerClass: `${_ctx.prefixCls}-dropdown`,
      onMousedown: _cache[4] || (_cache[4] = withModifiers(() => {}, ["prevent"]))
    }, {
      default: withCtx(() => [withDirectives(createVNode(_component_Tree, {
        ref: "refTree",
        expandedKeys: _ctx.currentExpandedKeys,
        "onUpdate:expandedKeys": _cache[3] || (_cache[3] = $event => _ctx.currentExpandedKeys = $event),
        selectedKeys: _ctx.selectedKeys,
        checkedKeys: _ctx.checkedKeys,
        data: _ctx.data,
        defaultExpandAll: _ctx.defaultExpandAll,
        accordion: _ctx.accordion,
        selectable: _ctx.treeSelectable,
        checkable: _ctx.treeCheckable,
        checkStrictly: _ctx.checkStrictly,
        cascade: _ctx.cascade,
        multiple: _ctx.multiple,
        childrenField: _ctx.childrenField,
        valueField: _ctx.valueField,
        labelField: _ctx.labelField,
        filterMethod: _ctx.filterMethod,
        inline: _ctx.inline,
        remote: _ctx.remote,
        loadData: _ctx.loadData,
        filterText: _ctx.filterText,
        filterTextHighlight: _ctx.filterTextHighlight,
        "onUpdate:nodeList": _ctx.onChangeNodeList,
        onSelect: _ctx.handleSelect,
        onCheck: _ctx.handleCheck
      }, null, 8 /* PROPS */, ["expandedKeys", "selectedKeys", "checkedKeys", "data", "defaultExpandAll", "accordion", "selectable", "checkable", "checkStrictly", "cascade", "multiple", "childrenField", "valueField", "labelField", "filterMethod", "inline", "remote", "loadData", "filterText", "filterTextHighlight", "onUpdate:nodeList", "onSelect", "onCheck"]), [[vShow, _ctx.data.length]]), withDirectives(createElementVNode("div", {
        class: normalizeClass(`${_ctx.prefixCls}-null`)
      }, toDisplayString(_ctx.listEmptyText), 3 /* TEXT, CLASS */), [[vShow, !_ctx.data.length]])]),
      _: 1 /* STABLE */
    }, 8 /* PROPS */, ["containerStyle", "containerClass"]))]),
    _: 1 /* STABLE */
  }, 8 /* PROPS */, ["modelValue", "popperClass", "appendToContainer", "getContainer", "disabled"])], 2 /* CLASS */);
}

script.render = render;
script.__file = "components/select-tree/selectTree.vue";

export { script as default, selectTreeProps };
