import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _createSuper from "@babel/runtime/helpers/esm/createSuper";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
// @ts-nocheck
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Trigger from '../rc-trigger';
import raf from '../rc-util/raf';
import KeyCode from '../rc-util/KeyCode';
import CSSMotion from '../rc-motion';
import classNames from 'classnames';
import { connect } from 'mini-store';
import SubPopupMenu from './SubPopupMenu';
import { placements, placementsRtl } from './placements';
import { noop, loopMenuItemRecursively, getMenuIdFromSubMenuEventKey, menuAllProps } from './util';
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))
  });
};

export var SubMenu = /*#__PURE__*/function (_React$Component) {
  _inherits(SubMenu, _React$Component);

  var _super = _createSuper(SubMenu);

  function SubMenu(props) {
    var _this;

    _classCallCheck(this, SubMenu);

    _this = _super.call(this, props);

    _this.onDestroy = function (key) {
      _this.props.onDestroy(key);
    };
    /**
     * note:
     *  This legacy code that `onKeyDown` is called by parent instead of dom self.
     *  which need return code to check if this event is handled
     */


    _this.onKeyDown = function (e) {
      var keyCode = e.keyCode;
      var menu = _this.menuInstance;
      var store = _this.props.store;

      var visible = _this.getVisible();

      if (keyCode === KeyCode.ENTER) {
        _this.onTitleClick(e);

        updateDefaultActiveFirst(store, _this.props.eventKey, true);
        return true;
      }

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


          updateDefaultActiveFirst(store, _this.props.eventKey, true);
        }

        return true;
      }

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

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

        if (!handled) {
          _this.triggerOpenChange(false);

          handled = true;
        }

        return handled;
      }

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

      return undefined;
    };

    _this.onOpenChange = function (e) {
      _this.props.onOpenChange(e);
    };

    _this.onPopupVisibleChange = function (visible) {
      _this.triggerOpenChange(visible, visible ? 'mouseenter' : 'mouseleave');
    };

    _this.onMouseEnter = function (e) {
      var _this$props = _this.props,
          key = _this$props.eventKey,
          onMouseEnter = _this$props.onMouseEnter,
          store = _this$props.store;
      updateDefaultActiveFirst(store, _this.props.eventKey, false);
      onMouseEnter({
        key: key,
        domEvent: e
      });
    };

    _this.onMouseLeave = function (e) {
      var _this$props2 = _this.props,
          parentMenu = _this$props2.parentMenu,
          eventKey = _this$props2.eventKey,
          onMouseLeave = _this$props2.onMouseLeave;
      parentMenu.subMenuInstance = _assertThisInitialized(_this);
      onMouseLeave({
        key: eventKey,
        domEvent: e
      });
    };

    _this.onTitleMouseEnter = function (domEvent) {
      var _this$props3 = _this.props,
          key = _this$props3.eventKey,
          onItemHover = _this$props3.onItemHover,
          onTitleMouseEnter = _this$props3.onTitleMouseEnter;
      onItemHover({
        key: key,
        hover: true
      });
      onTitleMouseEnter({
        key: key,
        domEvent: domEvent
      });
    };

    _this.onTitleMouseLeave = function (e) {
      var _this$props4 = _this.props,
          parentMenu = _this$props4.parentMenu,
          eventKey = _this$props4.eventKey,
          onItemHover = _this$props4.onItemHover,
          onTitleMouseLeave = _this$props4.onTitleMouseLeave;
      parentMenu.subMenuInstance = _assertThisInitialized(_this);
      onItemHover({
        key: eventKey,
        hover: false
      });
      onTitleMouseLeave({
        key: eventKey,
        domEvent: e
      });
    };

    _this.onTitleClick = function (e) {
      var _assertThisInitialize = _assertThisInitialized(_this),
          props = _assertThisInitialize.props;

      props.onTitleClick({
        key: props.eventKey,
        domEvent: e
      });

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

      _this.triggerOpenChange(!_this.getVisible(), 'click');

      updateDefaultActiveFirst(props.store, _this.props.eventKey, false);
    };

    _this.onSubMenuClick = function (info) {
      // in the case of overflowed submenu
      // onClick is not copied over
      if (typeof _this.props.onClick === 'function') {
        _this.props.onClick(_this.addKeyPath(info));
      }
    };

    _this.onSelect = function (info) {
      _this.props.onSelect(info);
    };

    _this.onDeselect = function (info) {
      _this.props.onDeselect(info);
    };

    _this.getPrefixCls = function () {
      return "".concat(_this.props.rootPrefixCls, "-submenu");
    };

    _this.getActiveClassName = function () {
      return "".concat(_this.getPrefixCls(), "-active");
    };

    _this.getDisabledClassName = function () {
      return "".concat(_this.getPrefixCls(), "-disabled");
    };

    _this.getSelectedClassName = function () {
      return "".concat(_this.getPrefixCls(), "-selected");
    };

    _this.getOpenClassName = function () {
      return "".concat(_this.props.rootPrefixCls, "-submenu-open");
    };

    _this.getVisible = function () {
      return _this.state.isOpen;
    };

    _this.getMode = function () {
      return _this.state.mode;
    };

    _this.saveMenuInstance = function (c) {
      // children menu instance
      _this.menuInstance = c;
    };

    _this.addKeyPath = function (info) {
      return _objectSpread(_objectSpread({}, info), {}, {
        keyPath: (info.keyPath || []).concat(_this.props.eventKey)
      });
    };

    _this.triggerOpenChange = function (open, type) {
      var key = _this.props.eventKey;

      var openChange = function openChange() {
        _this.onOpenChange({
          key: key,
          item: _assertThisInitialized(_this),
          trigger: type,
          open: open
        });
      };

      if (type === 'mouseenter') {
        // make sure mouseenter happen after other menu item's mouseleave
        _this.mouseenterTimeout = setTimeout(function () {
          openChange();
        }, 0);
      } else {
        openChange();
      }
    };

    _this.isChildrenSelected = function () {
      var ret = {
        find: false
      };
      loopMenuItemRecursively(_this.props.children, _this.props.selectedKeys, ret);
      return ret.find;
    };

    _this.isInlineMode = function () {
      return _this.getMode() === 'inline';
    };

    _this.adjustWidth = function () {
      /* istanbul ignore if */
      if (!_this.subMenuTitle || !_this.menuInstance) {
        return;
      }

      var popupMenu = ReactDOM.findDOMNode(_this.menuInstance);

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


      popupMenu.style.minWidth = "".concat(_this.subMenuTitle.offsetWidth, "px");
    };

    _this.saveSubMenuTitle = function (subMenuTitle) {
      _this.subMenuTitle = subMenuTitle;
    };

    _this.getBaseProps = function () {
      var _assertThisInitialize2 = _assertThisInitialized(_this),
          props = _assertThisInitialize2.props;

      var mergedMode = _this.getMode();

      return {
        mode: mergedMode === 'horizontal' ? 'vertical' : mergedMode,
        visible: _this.getVisible(),
        level: props.level + 1,
        inlineIndent: props.inlineIndent,
        focusable: false,
        onClick: _this.onSubMenuClick,
        onSelect: _this.onSelect,
        onDeselect: _this.onDeselect,
        onDestroy: _this.onDestroy,
        selectedKeys: props.selectedKeys,
        eventKey: "".concat(props.eventKey, "-menu-"),
        openKeys: props.openKeys,
        motion: props.motion,
        onOpenChange: _this.onOpenChange,
        subMenuOpenDelay: props.subMenuOpenDelay,
        parentMenu: _assertThisInitialized(_this),
        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,
        id: _this.internalMenuId,
        manualRef: _this.saveMenuInstance,
        itemIcon: props.itemIcon,
        expandIcon: props.expandIcon,
        direction: props.direction
      };
    };

    _this.getMotion = function (mode, visible) {
      var _assertThisInitialize3 = _assertThisInitialized(_this),
          haveRendered = _assertThisInitialize3.haveRendered;

      var _this$props5 = _this.props,
          motion = _this$props5.motion,
          rootPrefixCls = _this$props5.rootPrefixCls; // 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 mergedMotion = _objectSpread(_objectSpread({}, motion), {}, {
        leavedClassName: "".concat(rootPrefixCls, "-hidden"),
        removeOnLeave: false,
        motionAppear: haveRendered || !visible || mode !== 'inline'
      });

      return mergedMotion;
    };

    var store = props.store,
        eventKey = props.eventKey;

    var _store$getState = store.getState(),
        defaultActiveFirst = _store$getState.defaultActiveFirst;

    _this.isRootMenu = false;
    var value = false;

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

    updateDefaultActiveFirst(store, eventKey, value);
    _this.state = {
      mode: props.mode,
      isOpen: props.isOpen
    };
    return _this;
  }

  _createClass(SubMenu, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      this.componentDidUpdate();
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate() {
      var _this2 = this;

      var _this$props6 = this.props,
          mode = _this$props6.mode,
          parentMenu = _this$props6.parentMenu,
          manualRef = _this$props6.manualRef,
          isOpen = _this$props6.isOpen;

      var updateState = function updateState() {
        _this2.setState({
          mode: mode,
          isOpen: isOpen
        });
      }; // Delay sync when mode changed in case openKeys change not sync


      var isOpenChanged = isOpen !== this.state.isOpen;
      var isModeChanged = mode !== this.state.mode;

      if (isModeChanged || isOpenChanged) {
        raf.cancel(this.updateStateRaf);

        if (isModeChanged) {
          this.updateStateRaf = raf(updateState);
        } else {
          updateState();
        }
      } // invoke customized ref to expose component to mixin


      if (manualRef) {
        manualRef(this);
      }

      if (mode !== 'horizontal' || !(parentMenu === null || parentMenu === void 0 ? void 0 : parentMenu.isRootMenu) || !isOpen) {
        return;
      }

      this.minWidthTimeout = setTimeout(function () {
        return _this2.adjustWidth();
      }, 0);
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var _this$props7 = this.props,
          onDestroy = _this$props7.onDestroy,
          eventKey = _this$props7.eventKey;

      if (onDestroy) {
        onDestroy(eventKey);
      }
      /* istanbul ignore if */


      if (this.minWidthTimeout) {
        clearTimeout(this.minWidthTimeout);
      }
      /* istanbul ignore if */


      if (this.mouseenterTimeout) {
        clearTimeout(this.mouseenterTimeout);
      }

      raf.cancel(this.updateStateRaf);
    }
  }, {
    key: "renderPopupMenu",
    value: function renderPopupMenu(className, style) {
      var baseProps = this.getBaseProps();
      /**
       * zombiej: Why SubPopupMenu here?
       * Seems whatever popup or inline mode both will render SubPopupMenu.
       * It's controlled by Trigger for popup or not.
       */

      return /*#__PURE__*/React.createElement(SubPopupMenu, Object.assign({}, baseProps, {
        id: this.internalMenuId,
        className: className,
        style: style
      }), this.props.children);
    }
  }, {
    key: "renderChildren",
    value: function renderChildren() {
      var _this3 = this;

      var baseProps = this.getBaseProps();
      var mode = baseProps.mode,
          visible = baseProps.visible,
          forceSubMenuRender = baseProps.forceSubMenuRender,
          direction = baseProps.direction; // [Legacy] getMotion must be called before `haveRendered`

      var mergedMotion = this.getMotion(mode, visible);
      this.haveRendered = true;
      this.haveOpened = this.haveOpened || visible || forceSubMenuRender; // never rendered not planning to, don't render

      if (!this.haveOpened) {
        return /*#__PURE__*/React.createElement("div", null);
      }

      var sharedClassName = classNames("".concat(baseProps.prefixCls, "-sub"), _defineProperty({}, "".concat(baseProps.prefixCls, "-rtl"), direction === 'rtl'));

      if (!this.isInlineMode()) {
        return this.renderPopupMenu(sharedClassName);
      }

      return /*#__PURE__*/React.createElement(CSSMotion, Object.assign({
        visible: baseProps.visible
      }, mergedMotion), function (_ref) {
        var className = _ref.className,
            style = _ref.style;
        var mergedClassName = classNames(sharedClassName, className);
        return _this3.renderPopupMenu(mergedClassName, style);
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _classNames2, _props$parentMenu, _classNames3;

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

      var visible = this.getVisible();
      var prefixCls = this.getPrefixCls();
      var inline = this.isInlineMode();
      var mergedMode = this.getMode();
      var className = classNames(prefixCls, "".concat(prefixCls, "-").concat(mergedMode), (_classNames2 = {}, _defineProperty(_classNames2, props.className, !!props.className), _defineProperty(_classNames2, this.getOpenClassName(), visible), _defineProperty(_classNames2, this.getActiveClassName(), props.active || visible && !inline), _defineProperty(_classNames2, this.getDisabledClassName(), props.disabled), _defineProperty(_classNames2, this.getSelectedClassName(), this.isChildrenSelected()), _classNames2));

      if (!this.internalMenuId) {
        if (props.eventKey) {
          this.internalMenuId = "".concat(props.eventKey, "$Menu");
        } else {
          guid += 1;
          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 = {};
      var direction = props.direction;
      var isRTL = direction === 'rtl';

      if (inline) {
        if (isRTL) {
          style.paddingRight = props.inlineIndent * props.level;
        } else {
          style.paddingLeft = props.inlineIndent * props.level;
        }
      }

      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 (this.getVisible()) {
        ariaOwns = {
          'aria-owns': this.internalMenuId
        };
      } // expand custom icon should NOT be displayed in menu with horizontal mode.


      var icon = null;

      if (mergedMode !== 'horizontal') {
        icon = this.props.expandIcon; // ReactNode

        if (typeof this.props.expandIcon === 'function') {
          icon = /*#__PURE__*/React.createElement(this.props.expandIcon, _objectSpread({}, this.props));
        }
      }

      var title = /*#__PURE__*/React.createElement("div", Object.assign({
        ref: this.saveSubMenuTitle,
        style: style,
        className: "".concat(prefixCls, "-title"),
        role: "button"
      }, titleMouseEvents, titleClickEvents, {
        "aria-expanded": visible
      }, ariaOwns, {
        "aria-haspopup": "true",
        title: typeof props.title === 'string' ? props.title : undefined
      }), props.title, icon || /*#__PURE__*/React.createElement("i", {
        className: "".concat(prefixCls, "-arrow")
      }));
      var children = this.renderChildren();
      var getPopupContainer = ((_props$parentMenu = props.parentMenu) === null || _props$parentMenu === void 0 ? void 0 : _props$parentMenu.isRootMenu) ? props.parentMenu.props.getPopupContainer : function (triggerNode) {
        return triggerNode.parentNode;
      };
      var popupPlacement = popupPlacementMap[mergedMode];
      var popupAlign = props.popupOffset ? {
        offset: props.popupOffset
      } : {};
      var popupClassName = classNames((_classNames3 = {}, _defineProperty(_classNames3, props.popupClassName, props.popupClassName && !inline), _defineProperty(_classNames3, "".concat(prefixCls, "-rtl"), isRTL), _classNames3));
      var disabled = props.disabled,
          triggerSubMenuAction = props.triggerSubMenuAction,
          subMenuOpenDelay = props.subMenuOpenDelay,
          forceSubMenuRender = props.forceSubMenuRender,
          subMenuCloseDelay = props.subMenuCloseDelay,
          builtinPlacements = props.builtinPlacements;
      menuAllProps.forEach(function (key) {
        return delete props[key];
      }); // Set onClick to null, to ignore propagated onClick event

      delete props.onClick;
      var placement = isRTL ? Object.assign({}, placementsRtl, builtinPlacements) : Object.assign({}, placements, builtinPlacements);
      delete props.direction; // [Legacy] It's a fast fix,
      // but we should check if we can refactor this to make code more easy to understand

      var baseProps = this.getBaseProps();
      var mergedMotion = inline ? null : this.getMotion(baseProps.mode, baseProps.visible);
      return /*#__PURE__*/React.createElement("li", Object.assign({}, props, mouseEvents, {
        className: className,
        role: "menuitem"
      }), /*#__PURE__*/React.createElement(Trigger, {
        prefixCls: prefixCls,
        popupClassName: classNames("".concat(prefixCls, "-popup"), popupClassName),
        getPopupContainer: getPopupContainer,
        builtinPlacements: placement,
        popupPlacement: popupPlacement,
        popupVisible: inline ? false : visible,
        popupAlign: popupAlign,
        popup: inline ? null : children,
        action: disabled || inline ? [] : [triggerSubMenuAction],
        mouseEnterDelay: subMenuOpenDelay,
        mouseLeaveDelay: subMenuCloseDelay,
        onPopupVisibleChange: this.onPopupVisibleChange,
        forceRender: forceSubMenuRender,
        popupMotion: mergedMotion
      }, title), inline ? children : null);
    }
  }]);

  return SubMenu;
}(React.Component);
SubMenu.defaultProps = {
  onMouseEnter: noop,
  onMouseLeave: noop,
  onTitleMouseEnter: noop,
  onTitleMouseLeave: noop,
  onTitleClick: noop,
  manualRef: noop,
  mode: 'vertical',
  title: ''
};
var connected = connect(function (_ref2, _ref3) {
  var openKeys = _ref2.openKeys,
      activeKey = _ref2.activeKey,
      selectedKeys = _ref2.selectedKeys;
  var eventKey = _ref3.eventKey,
      subMenuKey = _ref3.subMenuKey;
  return {
    isOpen: openKeys.indexOf(eventKey) > -1,
    active: activeKey[subMenuKey] === eventKey,
    selectedKeys: selectedKeys
  };
})(SubMenu);
connected.isSubMenu = true;
export default connected;