import * as _vue from "vue";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

import FilterFilled from '@ant-design/icons-vue/FilterFilled';
import Menu, { SubMenu, Item as MenuItem } from '../vc-menu';
import closest from 'dom-closest';
import classNames from '../_util/classNames';
import shallowequal from '../_util/shallowequal';
import Dropdown from '../dropdown';
import Checkbox from '../checkbox';
import Radio from '../radio';
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
import { FilterMenuProps } from './interface';
import { initDefaultProps, isValidElement, findDOMNode } from '../_util/props-util';
import { cloneElement } from '../_util/vnode';
import BaseMixin2 from '../_util/BaseMixin2';
import { generateValueMaps } from './util';
import { watchEffect, reactive } from 'vue';

function stopPropagation(e) {
  e.stopPropagation();
}

export default {
  name: 'FilterMenu',
  mixins: [BaseMixin2],
  inheritAttrs: false,
  props: initDefaultProps(FilterMenuProps, {
    column: {}
  }),
  setup: function setup(nextProps) {
    var preProps = _objectSpread({}, nextProps);

    var selectedKeys = nextProps.selectedKeys,
        column = nextProps.column;
    var state = reactive({
      neverShown: false,
      sSelectedKeys: selectedKeys,
      sKeyPathOfSelectedItem: {},
      // 记录所有有选中子菜单的祖先菜单
      sVisible: 'filterDropdownVisible' in column ? column.filterDropdownVisible : false,
      sValueKeys: generateValueMaps(column.filters)
    });
    watchEffect(function () {
      var column = nextProps.column;

      if (!shallowequal(preProps.selectedKeys, nextProps.selectedKeys)) {
        state.sSelectedKeys = nextProps.selectedKeys;
      }

      if (!shallowequal((preProps.column || {}).filters, (nextProps.column || {}).filters)) {
        state.sValueKeys = generateValueMaps(nextProps.column.filters);
      }

      if ('filterDropdownVisible' in column) {
        state.sVisible = column.filterDropdownVisible;
      }

      preProps = _objectSpread({}, nextProps);
    }, {
      flush: 'sync'
    });
    return state;
  },
  mounted: function mounted() {
    var _this = this;

    var column = this.column;
    this.$nextTick(function () {
      _this.setNeverShown(column);
    });
  },
  updated: function updated() {
    var _this2 = this;

    var column = this.column;
    this.$nextTick(function () {
      _this2.setNeverShown(column);
    });
  },
  methods: {
    getDropdownVisible: function getDropdownVisible() {
      return this.neverShown ? false : this.sVisible;
    },
    setNeverShown: function setNeverShown(column) {
      var rootNode = findDOMNode(this);
      var filterBelongToScrollBody = !!closest(rootNode, ".ant-table-scroll");

      if (filterBelongToScrollBody) {
        // When fixed column have filters, there will be two dropdown menus
        // Filter dropdown menu inside scroll body should never be shown
        // To fix https://github.com/ant-design/ant-design/issues/5010 and
        // https://github.com/ant-design/ant-design/issues/7909
        this.neverShown = !!column.fixed;
      }
    },
    setSelectedKeys: function setSelectedKeys(_ref) {
      var selectedKeys = _ref.selectedKeys;
      this.setState({
        sSelectedKeys: selectedKeys
      });
    },
    setVisible: function setVisible(visible) {
      var column = this.column;

      if (!('filterDropdownVisible' in column)) {
        this.setState({
          sVisible: visible
        });
      }

      if (column.onFilterDropdownVisibleChange) {
        column.onFilterDropdownVisibleChange(visible);
      }
    },
    handleClearFilters: function handleClearFilters() {
      this.setState({
        sSelectedKeys: []
      }, this.handleConfirm);
    },
    handleConfirm: function handleConfirm() {
      this.setVisible(false); // Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date
      // https://github.com/ant-design/ant-design/issues/12284

      this.$forceUpdate();
      this.$nextTick(this.confirmFilter2);
    },
    onVisibleChange: function onVisibleChange(visible) {
      this.setVisible(visible);
      var column = this.$props.column; // https://github.com/ant-design/ant-design/issues/17833

      if (!visible && !(column.filterDropdown instanceof Function)) {
        this.confirmFilter2();
      }
    },
    handleMenuItemClick: function handleMenuItemClick(info) {
      var selectedKeys = this.sSelectedKeys;

      if (!info.keyPath || info.keyPath.length <= 1) {
        return;
      }

      var keyPathOfSelectedItem = this.sKeyPathOfSelectedItem;

      if (selectedKeys && selectedKeys.indexOf(info.key) >= 0) {
        // deselect SubMenu child
        delete keyPathOfSelectedItem[info.key];
      } else {
        // select SubMenu child
        keyPathOfSelectedItem[info.key] = info.keyPath;
      }

      this.setState({
        sKeyPathOfSelectedItem: keyPathOfSelectedItem
      });
    },
    hasSubMenu: function hasSubMenu() {
      var _this$column$filters = this.column.filters,
          filters = _this$column$filters === void 0 ? [] : _this$column$filters;
      return filters.some(function (item) {
        return !!(item.children && item.children.length > 0);
      });
    },
    confirmFilter2: function confirmFilter2() {
      var _this$$props = this.$props,
          column = _this$$props.column,
          propSelectedKeys = _this$$props.selectedKeys,
          confirmFilter = _this$$props.confirmFilter;
      var selectedKeys = this.sSelectedKeys,
          valueKeys = this.sValueKeys;
      var filterDropdown = column.filterDropdown;

      if (!shallowequal(selectedKeys, propSelectedKeys)) {
        confirmFilter(column, filterDropdown ? selectedKeys : selectedKeys.map(function (key) {
          return valueKeys[key];
        }).filter(function (key) {
          return key !== undefined;
        }));
      }
    },
    renderMenus: function renderMenus(items) {
      var _this3 = this;

      var _this$$props2 = this.$props,
          dropdownPrefixCls = _this$$props2.dropdownPrefixCls,
          prefixCls = _this$$props2.prefixCls;
      return items.map(function (item) {
        if (item.children && item.children.length > 0) {
          var sKeyPathOfSelectedItem = _this3.sKeyPathOfSelectedItem;
          var containSelected = Object.keys(sKeyPathOfSelectedItem).some(function (key) {
            return sKeyPathOfSelectedItem[key].indexOf(item.value) >= 0;
          });
          var subMenuCls = classNames("".concat(prefixCls, "-dropdown-submenu"), _defineProperty({}, "".concat(dropdownPrefixCls, "-submenu-contain-selected"), containSelected));
          return _vue.createVNode(SubMenu, {
            "title": item.text,
            "popupClassName": subMenuCls,
            "key": item.value.toString()
          }, {
            default: function _default() {
              return [_this3.renderMenus(item.children)];
            }
          });
        }

        return _this3.renderMenuItem(item);
      });
    },
    renderFilterIcon: function renderFilterIcon() {
      var _classNames2;

      var column = this.column,
          locale = this.locale,
          prefixCls = this.prefixCls,
          selectedKeys = this.selectedKeys;
      var filtered = selectedKeys && selectedKeys.length > 0;
      var filterIcon = column.filterIcon;

      if (typeof filterIcon === 'function') {
        filterIcon = filterIcon({
          filtered: filtered,
          column: column
        });
      }

      var dropdownIconClass = classNames((_classNames2 = {}, _defineProperty(_classNames2, "".concat(prefixCls, "-selected"), 'filtered' in column ? column.filtered : filtered), _defineProperty(_classNames2, "".concat(prefixCls, "-open"), this.getDropdownVisible()), _classNames2));

      if (!filterIcon) {
        return _vue.createVNode(FilterFilled, {
          "title": locale.filterTitle,
          "class": dropdownIconClass,
          "onClick": stopPropagation
        }, null);
      }

      if (filterIcon.length === 1 && isValidElement(filterIcon[0])) {
        var _filterIcon$props, _filterIcon$props2;

        return cloneElement(filterIcon[0], {
          title: ((_filterIcon$props = filterIcon.props) === null || _filterIcon$props === void 0 ? void 0 : _filterIcon$props.title) || locale.filterTitle,
          onClick: stopPropagation,
          class: classNames("".concat(prefixCls, "-icon"), dropdownIconClass, (_filterIcon$props2 = filterIcon.props) === null || _filterIcon$props2 === void 0 ? void 0 : _filterIcon$props2.class)
        });
      }

      return _vue.createVNode("span", {
        "class": classNames("".concat(prefixCls, "-icon"), dropdownIconClass)
      }, [filterIcon]);
    },
    renderMenuItem: function renderMenuItem(item) {
      var column = this.column;
      var selectedKeys = this.sSelectedKeys;
      var multiple = 'filterMultiple' in column ? column.filterMultiple : true; // We still need trade key as string since Menu render need string
      // const internalSelectedKeys = (selectedKeys || []).map(key => key.toString());

      var input = multiple ? _vue.createVNode(Checkbox, {
        "checked": selectedKeys && selectedKeys.indexOf(item.value.toString()) >= 0
      }, null) : _vue.createVNode(Radio, {
        "checked": selectedKeys && selectedKeys.indexOf(item.value.toString()) >= 0
      }, null);
      return _vue.createVNode(MenuItem, {
        "key": item.value
      }, {
        default: function _default() {
          return [input, _vue.createVNode("span", null, [item.text])];
        }
      });
    }
  },
  render: function render() {
    var _this4 = this;

    var originSelectedKeys = this.sSelectedKeys;
    var column = this.column,
        locale = this.locale,
        prefixCls = this.prefixCls,
        dropdownPrefixCls = this.dropdownPrefixCls,
        getPopupContainer = this.getPopupContainer; // default multiple selection in filter dropdown

    var multiple = 'filterMultiple' in column ? column.filterMultiple : true;
    var dropdownMenuClass = classNames(_defineProperty({}, "".concat(dropdownPrefixCls, "-menu-without-submenu"), !this.hasSubMenu()));
    var filterDropdown = column.filterDropdown;

    if (filterDropdown instanceof Function) {
      filterDropdown = filterDropdown({
        prefixCls: "".concat(dropdownPrefixCls, "-custom"),
        setSelectedKeys: function setSelectedKeys(selectedKeys) {
          return _this4.setSelectedKeys({
            selectedKeys: selectedKeys
          });
        },
        selectedKeys: originSelectedKeys,
        confirm: this.handleConfirm,
        clearFilters: this.handleClearFilters,
        filters: column.filters,
        visible: this.getDropdownVisible(),
        column: column
      });
    }

    var menus = filterDropdown ? _vue.createVNode(FilterDropdownMenuWrapper, {
      "class": "".concat(prefixCls, "-dropdown")
    }, {
      default: function _default() {
        return [filterDropdown];
      }
    }) : _vue.createVNode(FilterDropdownMenuWrapper, {
      "class": "".concat(prefixCls, "-dropdown")
    }, {
      default: function _default() {
        return [_vue.createVNode(Menu, {
          "multiple": multiple,
          "onClick": _this4.handleMenuItemClick,
          "prefixCls": "".concat(dropdownPrefixCls, "-menu"),
          "class": dropdownMenuClass,
          "onSelect": _this4.setSelectedKeys,
          "onDeselect": _this4.setSelectedKeys,
          "selectedKeys": originSelectedKeys && originSelectedKeys.map(function (val) {
            return val.toString();
          }),
          "getPopupContainer": getPopupContainer,
          "children": _this4.renderMenus(column.filters)
        }, null), _vue.createVNode("div", {
          "class": "".concat(prefixCls, "-dropdown-btns")
        }, [_vue.createVNode("a", {
          "class": "".concat(prefixCls, "-dropdown-link confirm"),
          "onClick": _this4.handleConfirm
        }, [locale.filterConfirm]), _vue.createVNode("a", {
          "class": "".concat(prefixCls, "-dropdown-link clear"),
          "onClick": _this4.handleClearFilters
        }, [locale.filterReset])])];
      }
    });
    return _vue.createVNode(Dropdown, {
      "trigger": ['click'],
      "placement": "bottomRight",
      "visible": this.getDropdownVisible(),
      "onVisibleChange": this.onVisibleChange,
      "getPopupContainer": getPopupContainer,
      "forceRender": true,
      "overlay": menus
    }, {
      default: function _default() {
        return [_this4.renderFilterIcon()];
      }
    });
  }
};