import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";

/**
 * Modal.jsx
 *
 * @Author: jruif
 * @Date: 2017/7/7 下午9:07
 *
 * todo: 移除Box，使用Overlay & Portal组件重写
 */
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group';
import { ariaHidden, ownerDocument } from './modalUtil';
import TrapFocus from './TrapFocus';
import Portal from '../portal';
import IconButton from '../button/IconButton';
import Close from '../icons/internals/Close';
import ModalManager from './ModalManager';
import ModalHeader from './ModalHeader';
import ModalFooter from './ModalFooter';
import ModalContent from './ModalContent';

function getContainer(container, defaultContainer) {
  container = typeof container === 'function' ? container() : container;
  return ReactDOM.findDOMNode(container) || defaultContainer;
}
/**
 * Modal
 */


var Modal =
/*#__PURE__*/
function (_Component) {
  _inherits(Modal, _Component);

  _createClass(Modal, null, [{
    key: "getDerivedStateFromProps",
    value: function getDerivedStateFromProps(nextProps) {
      if (nextProps.isOpen) {
        return {
          exited: false
        };
      }

      return null;
    }
  }]);

  function Modal(props) {
    var _this;

    _classCallCheck(this, Modal);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Modal).call(this));

    _defineProperty(_assertThisInitialized(_this), "mounted", false);

    _defineProperty(_assertThisInitialized(_this), "handleOpen", function () {
      var _this$props = _this.props,
          container = _this$props.container,
          manager = _this$props.manager;

      var doc = _this.getDoc();

      var modalContainer = getContainer(container, doc.body);
      manager.add(_assertThisInitialized(_this), modalContainer);

      if (_this.modalRef) {
        _this.handleOpened();
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleRendered", function () {
      var _this$props2 = _this.props,
          isOpen = _this$props2.isOpen,
          onRendered = _this$props2.onRendered;

      if (onRendered) {
        onRendered();
      }

      if (isOpen) {
        _this.handleOpened();
      } else {
        ariaHidden(_this.modalRef, true);
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleOpened", function () {
      var manager = _this.props.manager;
      manager.mount(_assertThisInitialized(_this)); // Fix a bug on Chrome where the scroll isn't initially 0.

      _this.modalRef.scrollTop = 0;
    });

    _defineProperty(_assertThisInitialized(_this), "handleClose", function (reason) {
      var _this$props3 = _this.props,
          closeAfterTransition = _this$props3.closeAfterTransition,
          manager = _this$props3.manager;
      /* If the component does not have a transition or is unmounting remove the Modal
      otherwise let the transition handle removing the style, this prevents elements
      moving around when the Modal is closed. */

      if (!closeAfterTransition || reason === 'unmount') {
        manager.remove(_assertThisInitialized(_this));
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleExited", function () {
      var _this$props4 = _this.props,
          closeAfterTransition = _this$props4.closeAfterTransition,
          manager = _this$props4.manager,
          onExited = _this$props4.onExited;

      if (onExited) {
        onExited();
      }

      if (closeAfterTransition) {
        manager.remove(_assertThisInitialized(_this));
      }

      _this.setState({
        exited: true
      });
    });

    _defineProperty(_assertThisInitialized(_this), "handleBackdropClick", function (event) {
      if (event.target !== event.currentTarget) {
        return;
      }

      var _this$props5 = _this.props,
          onBackdropClick = _this$props5.onBackdropClick,
          disableBackdropClick = _this$props5.disableBackdropClick,
          onClose = _this$props5.onClose;

      if (onBackdropClick) {
        onBackdropClick(event);
      }

      if (!disableBackdropClick && onClose) {
        onClose(event, 'backdropClick');
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) {
      // event.defaultPrevented:
      //
      // Ignore events that have been `event.preventDefault()` marked.
      // preventDefault() is meant to stop default behaviours like
      // clicking a checkbox to check it, hitting a button to submit a form,
      // and hitting left arrow to move the cursor in a text input etc.
      // Only special HTML elements have these default bahaviours.
      //
      // To remove in v4.
      if (event.key !== 'Escape' || !_this.isTopModal()) {
        return;
      } // Swallow the event, in case someone is listening for the escape key on the body.


      event.stopPropagation();
      var _this$props6 = _this.props,
          onEscapeKeyDown = _this$props6.onEscapeKeyDown,
          disableEscapeKeyDown = _this$props6.disableEscapeKeyDown,
          onClose = _this$props6.onClose;

      if (onEscapeKeyDown) {
        onEscapeKeyDown(event);
      }

      if (!disableEscapeKeyDown && onClose) {
        onClose(event, 'escapeKeyDown');
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handlePortalRef", function (ref) {
      _this.mountNode = ref ? ref.getMountNode() : ref;
    });

    _defineProperty(_assertThisInitialized(_this), "handleModalRef", function (ref) {
      _this.modalRef = ref;
    });

    _defineProperty(_assertThisInitialized(_this), "isTopModal", function () {
      return _this.props.manager.isTopModal(_assertThisInitialized(_this));
    });

    _defineProperty(_assertThisInitialized(_this), "getDoc", function () {
      return ownerDocument(_this.mountNode);
    });

    _defineProperty(_assertThisInitialized(_this), "handleMouseDown", function (event) {
      _this.mouseDownTarget = event.target;
    });

    _defineProperty(_assertThisInitialized(_this), "handleBackdropClick", function (event) {
      // Ignore the events not coming from the "backdrop"
      // We don't want to close the dialog when clicking the dialog content.
      if (event.target !== event.currentTarget) {
        return;
      } // Make sure the event starts and ends on the same DOM element.


      if (event.target !== _this.mouseDownTarget) {
        return;
      }

      var _this$props7 = _this.props,
          onBackdropClick = _this$props7.onBackdropClick,
          disableBackdropClick = _this$props7.disableBackdropClick,
          onClose = _this$props7.onClose;
      _this.mouseDownTarget = null;

      if (onBackdropClick) {
        onBackdropClick(event);
      }

      if (!disableBackdropClick && onClose) {
        onClose(event, 'backdropClick');
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleCloseButtonClick", function (event) {
      var onClose = _this.props.onClose;

      if (onClose) {
        onClose(event, 'buttonClick');
      }
    });

    _this.state = {
      exited: !props.isOpen
    };
    return _this;
  }

  _createClass(Modal, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      this.mounted = true;
      var isOpen = this.props.isOpen;

      if (isOpen) {
        this.handleOpen();
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      var isOpen = this.props.isOpen;

      if (prevProps.isOpen && !isOpen) {
        this.handleClose();
      } else if (!prevProps.isOpen && isOpen) {
        this.handleOpen();
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.mounted = false;
      var isOpen = this.props.isOpen;
      var exited = this.state.exited;

      if (isOpen || !exited) {
        this.handleClose('unmount');
      }
    }
  }, {
    key: "render",
    value: function render() {
      var _this$props8 = this.props,
          className = _this$props8.className,
          portalClassName = _this$props8.portalClassName,
          prefixCls = _this$props8.prefixCls,
          overlayClassName = _this$props8.overlayClassName,
          title = _this$props8.title,
          animationName = _this$props8.animationName,
          actions = _this$props8.actions,
          hideCloseButton = _this$props8.hideCloseButton,
          children = _this$props8.children,
          size = _this$props8.size,
          BackdropComponent = _this$props8.BackdropComponent,
          BackdropProps = _this$props8.BackdropProps,
          classes = _this$props8.classes,
          closeAfterTransition = _this$props8.closeAfterTransition,
          container = _this$props8.container,
          disableAutoFocus = _this$props8.disableAutoFocus,
          disableBackdropClick = _this$props8.disableBackdropClick,
          disableEnforceFocus = _this$props8.disableEnforceFocus,
          disableEscapeKeyDown = _this$props8.disableEscapeKeyDown,
          disablePortal = _this$props8.disablePortal,
          disableRestoreFocus = _this$props8.disableRestoreFocus,
          hideBackdrop = _this$props8.hideBackdrop,
          keepMounted = _this$props8.keepMounted,
          manager = _this$props8.manager,
          onBackdropClick = _this$props8.onBackdropClick,
          onClose = _this$props8.onClose,
          onEscapeKeyDown = _this$props8.onEscapeKeyDown,
          onRendered = _this$props8.onRendered,
          isOpen = _this$props8.isOpen,
          other = _objectWithoutProperties(_this$props8, ["className", "portalClassName", "prefixCls", "overlayClassName", "title", "animationName", "actions", "hideCloseButton", "children", "size", "BackdropComponent", "BackdropProps", "classes", "closeAfterTransition", "container", "disableAutoFocus", "disableBackdropClick", "disableEnforceFocus", "disableEscapeKeyDown", "disablePortal", "disableRestoreFocus", "hideBackdrop", "keepMounted", "manager", "onBackdropClick", "onClose", "onEscapeKeyDown", "onRendered", "isOpen"]);

      var exited = this.state.exited;

      if (!keepMounted && !isOpen && exited || !children) {
        return null;
      }

      var closeButton = hideCloseButton ? null : React.createElement(IconButton, {
        className: "".concat(prefixCls, "-close"),
        onClick: this.handleCloseButtonClick,
        variant: "text"
      }, React.createElement(Close, null));
      return React.createElement(Portal, {
        ref: this.handlePortalRef,
        container: container,
        disablePortal: disablePortal,
        onRendered: this.handleRendered
      }, React.createElement("div", _extends({
        ref: this.handleModalRef,
        onKeyDown: this.handleKeyDown,
        role: "presentation",
        className: classNames(prefixCls, className, _defineProperty({}, "".concat(prefixCls, "-hidden"), exited))
      }, other), hideBackdrop ? null : React.createElement(CSSTransition, {
        in: isOpen,
        timeout: 500,
        classNames: "".concat(prefixCls, "-backdrop"),
        appear: true
      }, React.createElement("div", {
        onClick: this.handleBackdropClick,
        "aria-hidden": "true",
        className: "".concat(prefixCls, "-backdrop")
      })), React.createElement(TrapFocus, {
        disableEnforceFocus: disableEnforceFocus,
        disableAutoFocus: disableAutoFocus,
        disableRestoreFocus: disableRestoreFocus,
        getDoc: this.getDoc,
        isEnabled: this.isTopModal,
        isOpen: isOpen
      }, React.createElement(CSSTransition, {
        in: isOpen,
        timeout: 300,
        classNames: "".concat(prefixCls, "-container-").concat(animationName),
        appear: true,
        onExited: this.handleExited
      }, React.createElement("div", {
        className: "".concat(prefixCls, "-container"),
        role: "document",
        onClick: this.handleBackdropClick,
        onMouseDown: this.handleMouseDown
      }, React.createElement("div", {
        className: classNames("".concat(prefixCls, "-body"), "".concat(prefixCls, "-body-").concat(size))
      }, title ? React.createElement(ModalHeader, {
        closeButton: closeButton
      }, title) : closeButton, children ? React.createElement(ModalContent, null, children) : null, actions ? React.createElement(ModalFooter, null, actions) : null))))));
    }
  }]);

  return Modal;
}(Component);

_defineProperty(Modal, "defaultProps", {
  prefixCls: 'ne-modal',
  hideCloseButton: false,
  size: 'medium',
  manager: new ModalManager(),
  animationName: 'scale' // parentSelector: document.body,

});

_defineProperty(Modal, "propTypes", {
  /**
   * 类前缀
   * */
  prefixCls: PropTypes.string,

  /** 是否隐藏关闭按钮 */
  hideCloseButton: PropTypes.bool,

  /** 是否打开 */
  isOpen: PropTypes.bool,

  /** 动画类型 */
  animationName: PropTypes.oneOf(['scale', 'slide-up', 'slide-down']),

  /**
   * 组件尺寸
   */
  size: PropTypes.oneOf(['small', 'medium', 'large']),

  /**
   * 是否隐藏遮罩层
   */
  hideBackdrop: PropTypes.bool,

  /**
   * 是否禁用遮罩层点击关闭
   */
  disableBackdropClick: PropTypes.bool,

  /**
   * 是否禁用esc关闭
   */
  disableEscapeKeyDown: PropTypes.bool,

  /**
   * 自定义按钮
   */
  actions: PropTypes.node
});

export default Modal;