import * as _vue from "vue";

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 _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

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 { Transition, inject, provide } from 'vue';
import omit from 'omit.js';
import PropTypes from '../_util/vue-types';
import Trigger from '../vc-trigger';
import KeyCode from '../_util/KeyCode';
import { connect } from '../_util/store';
import SubPopupMenu from './SubPopupMenu';
import placements from './placements';
import BaseMixin from '../_util/BaseMixin';
import { getComponent, filterEmpty, getSlot, splitAttrs, findDOMNode } from '../_util/props-util';
import { requestAnimationTimeout, cancelAnimationTimeout } from '../_util/requestAnimationTimeout';
import { noop, loopMenuItemRecursively, getMenuIdFromSubMenuEventKey } from './util';
import getTransitionProps from '../_util/getTransitionProps';
var guid = 0;
var popupPlacementMap = {
  horizontal: 'bottomLeft',
  vertical: 'rightTop',
  'vertical-left': 'rightTop',
  'vertical-right': 'leftTop'
};

var updateDefaultActiveFirst = function updateDefaultActiveFirst(store, eventKey, defaultActiveFirst) {
  var menuId = getMenuIdFromSubMenuEventKey(eventKey);
  var state = store.getState();
  store.setState({
    defaultActiveFirst: _objectSpread(_objectSpread({}, state.defaultActiveFirst), {}, _defineProperty({}, menuId, defaultActiveFirst))
  });
};

var SubMenu = {
  name: 'SubMenu',
  inheritAttrs: false,
  props: {
    title: PropTypes.any,
    selectedKeys: PropTypes.array.def([]),
    openKeys: PropTypes.array.def([]),
    openChange: PropTypes.func.def(noop),
    rootPrefixCls: PropTypes.string,
    eventKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    multiple: PropTypes.bool,
    active: PropTypes.bool,
    // TODO: remove
    isRootMenu: PropTypes.bool.def(false),
    index: PropTypes.number,
    triggerSubMenuAction: PropTypes.string,
    popupClassName: PropTypes.string,
    getPopupContainer: PropTypes.func,
    forceSubMenuRender: PropTypes.bool,
    openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
    disabled: PropTypes.bool,
    subMenuOpenDelay: PropTypes.number.def(0.1),
    subMenuCloseDelay: PropTypes.number.def(0.1),
    level: PropTypes.number.def(1),
    inlineIndent: PropTypes.number.def(24),
    openTransitionName: PropTypes.string,
    popupOffset: PropTypes.array,
    isOpen: PropTypes.bool,
    store: PropTypes.object,
    mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']).def('vertical'),
    manualRef: PropTypes.func.def(noop),
    builtinPlacements: PropTypes.object.def(function () {
      return {};
    }),
    itemIcon: PropTypes.any,
    expandIcon: PropTypes.any,
    subMenuKey: PropTypes.string,
    theme: PropTypes.string
  },
  mixins: [BaseMixin],
  isSubMenu: true,
  setup: function setup() {
    return {
      parentMenu: inject('parentMenu', undefined)
    };
  },
  created: function created() {
    provide('parentMenu', this);
  },
  data: function data() {
    var props = this.$props;
    var store = props.store;
    var eventKey = props.eventKey;
    var defaultActiveFirst = store.getState().defaultActiveFirst;
    var value = false;

    if (defaultActiveFirst) {
      value = defaultActiveFirst[eventKey];
    }

    updateDefaultActiveFirst(store, eventKey, value);
    this.internalMenuId = undefined;
    this.haveRendered = undefined;
    this.haveOpened = undefined;
    this.subMenuTitle = undefined;
    return {// defaultActiveFirst: false,
    };
  },
  mounted: function mounted() {
    var _this = this;

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

    this.$nextTick(function () {
      _this2.handleUpdated();
    });
  },
  beforeUnmount: function beforeUnmount() {
    var eventKey = this.eventKey;

    this.__emit('destroy', eventKey);
    /* istanbul ignore if */


    if (this.minWidthTimeout) {
      cancelAnimationTimeout(this.minWidthTimeout);
      this.minWidthTimeout = null;
    }
    /* istanbul ignore if */


    if (this.mouseenterTimeout) {
      cancelAnimationTimeout(this.mouseenterTimeout);
      this.mouseenterTimeout = null;
    }
  },
  methods: {
    handleUpdated: function handleUpdated() {
      var _this3 = this;

      var mode = this.mode,
          parentMenu = this.parentMenu,
          manualRef = this.manualRef; // invoke customized ref to expose component to mixin

      if (manualRef) {
        manualRef(this);
      }

      if (mode !== 'horizontal' || !parentMenu.isRootMenu || !this.isOpen) {
        return;
      }

      this.minWidthTimeout = requestAnimationTimeout(function () {
        return _this3.adjustWidth();
      }, 0);
    },
    onKeyDown: function onKeyDown(e) {
      var keyCode = e.keyCode;
      var menu = this.menuInstance;
      var _this$$props = this.$props,
          store = _this$$props.store,
          isOpen = _this$$props.isOpen;

      if (keyCode === KeyCode.ENTER) {
        this.onTitleClick(e);
        updateDefaultActiveFirst(store, this.eventKey, true);
        return true;
      }

      if (keyCode === KeyCode.RIGHT) {
        if (isOpen) {
          menu.onKeyDown(e);
        } else {
          this.triggerOpenChange(true); // need to update current menu's defaultActiveFirst value

          updateDefaultActiveFirst(store, this.eventKey, true);
        }

        return true;
      }

      if (keyCode === KeyCode.LEFT) {
        var handled;

        if (isOpen) {
          handled = menu.onKeyDown(e);
        } else {
          return undefined;
        }

        if (!handled) {
          this.triggerOpenChange(false);
          handled = true;
        }

        return handled;
      }

      if (isOpen && (keyCode === KeyCode.UP || keyCode === KeyCode.DOWN)) {
        return menu.onKeyDown(e);
      }

      return undefined;
    },
    onPopupVisibleChange: function onPopupVisibleChange(visible) {
      this.triggerOpenChange(visible, visible ? 'mouseenter' : 'mouseleave');
    },
    onMouseEnter: function onMouseEnter(e) {
      var _this$$props2 = this.$props,
          key = _this$$props2.eventKey,
          store = _this$$props2.store;
      updateDefaultActiveFirst(store, key, false);

      this.__emit('mouseenter', {
        key: key,
        domEvent: e
      });
    },
    onMouseLeave: function onMouseLeave(e) {
      var eventKey = this.eventKey;

      this.__emit('mouseleave', {
        key: eventKey,
        domEvent: e
      });
    },
    onTitleMouseEnter: function onTitleMouseEnter(domEvent) {
      var key = this.$props.eventKey;

      this.__emit('itemHover', {
        key: key,
        hover: true
      });

      this.__emit('titleMouseenter', {
        key: key,
        domEvent: domEvent
      });
    },
    onTitleMouseLeave: function onTitleMouseLeave(e) {
      var eventKey = this.eventKey;

      this.__emit('itemHover', {
        key: eventKey,
        hover: false
      });

      this.__emit('titleMouseleave', {
        key: eventKey,
        domEvent: e
      });
    },
    onTitleClick: function onTitleClick(e) {
      var _this$$props3 = this.$props,
          triggerSubMenuAction = _this$$props3.triggerSubMenuAction,
          eventKey = _this$$props3.eventKey,
          isOpen = _this$$props3.isOpen,
          store = _this$$props3.store;

      this.__emit('titleClick', {
        key: eventKey,
        domEvent: e
      });

      if (triggerSubMenuAction === 'hover') {
        return;
      }

      this.triggerOpenChange(!isOpen, 'click');
      updateDefaultActiveFirst(store, eventKey, false);
    },
    onSubMenuClick: function onSubMenuClick(info) {
      this.__emit('click', this.addKeyPath(info));
    },
    getPrefixCls: function getPrefixCls() {
      return "".concat(this.$props.rootPrefixCls, "-submenu");
    },
    getActiveClassName: function getActiveClassName() {
      return "".concat(this.getPrefixCls(), "-active");
    },
    getDisabledClassName: function getDisabledClassName() {
      return "".concat(this.getPrefixCls(), "-disabled");
    },
    getSelectedClassName: function getSelectedClassName() {
      return "".concat(this.getPrefixCls(), "-selected");
    },
    getOpenClassName: function getOpenClassName() {
      return "".concat(this.$props.rootPrefixCls, "-submenu-open");
    },
    saveMenuInstance: function saveMenuInstance(c) {
      // children menu instance
      this.menuInstance = c;
    },
    addKeyPath: function addKeyPath(info) {
      return _objectSpread(_objectSpread({}, info), {}, {
        keyPath: (info.keyPath || []).concat(this.$props.eventKey)
      });
    },
    // triggerOpenChange (open, type) {
    //   const key = this.$props.eventKey
    //   this.__emit('openChange', {
    //     key,
    //     item: this,
    //     trigger: type,
    //     open,
    //   })
    // },
    triggerOpenChange: function triggerOpenChange(open, type) {
      var _this4 = this;

      var key = this.$props.eventKey;

      var openChange = function openChange() {
        _this4.__emit('openChange', {
          key: key,
          item: _this4,
          trigger: type,
          open: open
        });
      };

      if (type === 'mouseenter') {
        // make sure mouseenter happen after other menu item's mouseleave
        this.mouseenterTimeout = requestAnimationTimeout(function () {
          openChange();
        }, 0);
      } else {
        openChange();
      }
    },
    isChildrenSelected: function isChildrenSelected() {
      var ret = {
        find: false
      };
      loopMenuItemRecursively(getSlot(this), this.$props.selectedKeys, ret);
      return ret.find;
    },
    // isOpen () {
    //   return this.$props.openKeys.indexOf(this.$props.eventKey) !== -1
    // },
    adjustWidth: function adjustWidth() {
      /* istanbul ignore if */
      if (!this.subMenuTitle || !this.menuInstance) {
        return;
      }

      var popupMenu = findDOMNode(this.menuInstance);

      if (popupMenu.offsetWidth >= this.subMenuTitle.offsetWidth) {
        return;
      }
      /* istanbul ignore next */


      popupMenu.style.minWidth = "".concat(this.subMenuTitle.offsetWidth, "px");
    },
    saveSubMenuTitle: function saveSubMenuTitle(subMenuTitle) {
      this.subMenuTitle = subMenuTitle;
    },
    renderChildren: function renderChildren(children) {
      var props = _objectSpread(_objectSpread({}, this.$props), this.$attrs);

      var subPopupMenuProps = {
        mode: props.mode === 'horizontal' ? 'vertical' : props.mode,
        visible: props.isOpen,
        level: props.level + 1,
        inlineIndent: props.inlineIndent,
        focusable: false,
        selectedKeys: props.selectedKeys,
        eventKey: "".concat(props.eventKey, "-menu-"),
        openKeys: props.openKeys,
        openTransitionName: props.openTransitionName,
        openAnimation: props.openAnimation,
        subMenuOpenDelay: props.subMenuOpenDelay,
        subMenuCloseDelay: props.subMenuCloseDelay,
        forceSubMenuRender: props.forceSubMenuRender,
        triggerSubMenuAction: props.triggerSubMenuAction,
        builtinPlacements: props.builtinPlacements,
        defaultActiveFirst: props.store.getState().defaultActiveFirst[getMenuIdFromSubMenuEventKey(props.eventKey)],
        multiple: props.multiple,
        prefixCls: props.rootPrefixCls,
        manualRef: this.saveMenuInstance,
        itemIcon: getComponent(this, 'itemIcon'),
        expandIcon: getComponent(this, 'expandIcon'),
        children: children,
        onClick: this.onSubMenuClick,
        onSelect: props.onSelect || noop,
        onDeselect: props.onDeselect || noop,
        onOpenChange: props.onOpenChange || noop,
        id: this.internalMenuId
      };
      var haveRendered = this.haveRendered;
      this.haveRendered = true;
      this.haveOpened = this.haveOpened || subPopupMenuProps.visible || subPopupMenuProps.forceSubMenuRender; // never rendered not planning to, don't render

      if (!this.haveOpened) {
        return _vue.createVNode("div", null, null);
      } // don't show transition on first rendering (no animation for opened menu)
      // show appear transition if it's not visible (not sure why)
      // show appear transition if it's not inline mode


      var transitionAppear = haveRendered || !subPopupMenuProps.visible || !subPopupMenuProps.mode === 'inline';
      subPopupMenuProps.class = " ".concat(subPopupMenuProps.prefixCls, "-sub");
      var transitionProps = {
        appear: transitionAppear,
        css: false
      };

      if (subPopupMenuProps.openTransitionName) {
        transitionProps = getTransitionProps(subPopupMenuProps.openTransitionName, {
          appear: transitionAppear
        });
      } else if (_typeof(subPopupMenuProps.openAnimation) === 'object') {
        transitionProps = _objectSpread(_objectSpread({}, transitionProps), subPopupMenuProps.openAnimation || {});

        if (!transitionAppear) {
          transitionProps.appear = false;
        }
      } else if (typeof subPopupMenuProps.openAnimation === 'string') {
        transitionProps = getTransitionProps(subPopupMenuProps.openAnimation, {
          appear: transitionAppear
        });
      }

      return _vue.createVNode(Transition, transitionProps, {
        default: function _default() {
          return [_vue.withDirectives(_vue.createVNode(SubPopupMenu, subPopupMenuProps, null), [[_vue.vShow, props.isOpen]])];
        }
      });
    }
  },
  render: function render() {
    var _className;

    var props = _objectSpread(_objectSpread({}, this.$props), this.$attrs);

    var _splitAttrs = splitAttrs(props),
        onEvents = _splitAttrs.onEvents;

    var rootPrefixCls = this.rootPrefixCls,
        parentMenu = this.parentMenu;
    var isOpen = props.isOpen;
    var prefixCls = this.getPrefixCls();
    var isInlineMode = props.mode === 'inline';
    var className = (_className = {}, _defineProperty(_className, prefixCls, true), _defineProperty(_className, "".concat(prefixCls, "-").concat(props.mode), true), _defineProperty(_className, props.class, !!props.class), _defineProperty(_className, this.getOpenClassName(), isOpen), _defineProperty(_className, this.getActiveClassName(), props.active || isOpen && !isInlineMode), _defineProperty(_className, this.getDisabledClassName(), props.disabled), _defineProperty(_className, this.getSelectedClassName(), this.isChildrenSelected()), _className);

    if (!this.internalMenuId) {
      if (props.eventKey) {
        this.internalMenuId = "".concat(props.eventKey, "$Menu");
      } else {
        this.internalMenuId = "$__$".concat(++guid, "$Menu");
      }
    }

    var mouseEvents = {};
    var titleClickEvents = {};
    var titleMouseEvents = {};

    if (!props.disabled) {
      mouseEvents = {
        onMouseleave: this.onMouseLeave,
        onMouseenter: this.onMouseEnter
      }; // only works in title, not outer li

      titleClickEvents = {
        onClick: this.onTitleClick
      };
      titleMouseEvents = {
        onMouseenter: this.onTitleMouseEnter,
        onMouseleave: this.onTitleMouseLeave
      };
    }

    var style = {};

    if (isInlineMode) {
      style.paddingLeft = "".concat(props.inlineIndent * props.level, "px");
    }

    var ariaOwns = {}; // only set aria-owns when menu is open
    // otherwise it would be an invalid aria-owns value
    // since corresponding node cannot be found

    if (isOpen) {
      ariaOwns = {
        'aria-owns': this.internalMenuId
      };
    }

    var titleProps = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
      'aria-expanded': isOpen
    }, ariaOwns), {}, {
      'aria-haspopup': 'true',
      title: typeof props.title === 'string' ? props.title : undefined
    }, titleMouseEvents), titleClickEvents), {}, {
      style: style,
      class: "".concat(prefixCls, "-title"),
      ref: this.saveSubMenuTitle
    }); // expand custom icon should NOT be displayed in menu with horizontal mode.


    var icon = null;

    if (props.mode !== 'horizontal') {
      icon = getComponent(this, 'expandIcon', props);
    }

    var title = _vue.createVNode("div", titleProps, [getComponent(this, 'title'), icon || _vue.createVNode("i", {
      "class": "".concat(prefixCls, "-arrow")
    }, null)]);

    var children = this.renderChildren(filterEmpty(getSlot(this)));
    var getPopupContainer = this.parentMenu.isRootMenu ? this.parentMenu.getPopupContainer : function (triggerNode) {
      return triggerNode.parentNode;
    };
    var popupPlacement = popupPlacementMap[props.mode];
    var popupAlign = props.popupOffset ? {
      offset: props.popupOffset
    } : {};
    var popupClassName = props.mode === 'inline' ? '' : props.popupClassName || '';
    popupClassName = "".concat(prefixCls, "-popup ").concat(rootPrefixCls, "-").concat(parentMenu.theme, " ").concat(popupClassName);

    var liProps = _objectSpread(_objectSpread(_objectSpread({}, omit(onEvents, ['onClick'])), mouseEvents), {}, {
      class: className,
      style: props.style
    });

    return _vue.createVNode("li", _vue.mergeProps(liProps, {
      "role": "menuitem"
    }), [isInlineMode && title, isInlineMode && children, !isInlineMode && _vue.createVNode(Trigger, {
      "prefixCls": prefixCls,
      "popupClassName": popupClassName,
      "getPopupContainer": getPopupContainer,
      "builtinPlacements": placements,
      "popupPlacement": popupPlacement,
      "popupVisible": isOpen,
      "popupAlign": popupAlign,
      "action": props.disabled ? [] : [props.triggerSubMenuAction],
      "mouseEnterDelay": props.subMenuOpenDelay,
      "mouseLeaveDelay": props.subMenuCloseDelay,
      "onPopupVisibleChange": this.onPopupVisibleChange,
      "forceRender": props.forceSubMenuRender,
      "popup": children
    }, {
      default: function _default() {
        return [title];
      }
    })]);
  }
};
var connected = connect(function (_ref, _ref2) {
  var openKeys = _ref.openKeys,
      activeKey = _ref.activeKey,
      selectedKeys = _ref.selectedKeys;
  var eventKey = _ref2.eventKey,
      subMenuKey = _ref2.subMenuKey;
  return {
    isOpen: openKeys.indexOf(eventKey) > -1,
    active: activeKey[subMenuKey] === eventKey,
    selectedKeys: selectedKeys
  };
})(SubMenu);
connected.isSubMenu = true;
export default connected;