'use strict';

exports.__esModule = true;

var _pick2 = require('lodash/pick');

var _pick3 = _interopRequireDefault(_pick2);

var _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; };

var _react = require('react');

var React = _interopRequireWildcard(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _reactDom = require('react-dom');

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _setDisplayName = require('recompose/setDisplayName');

var _setDisplayName2 = _interopRequireDefault(_setDisplayName);

var _setStatic = require('recompose/setStatic');

var _setStatic2 = _interopRequireDefault(_setStatic);

var _Modal = require('rsuite-utils/lib/Overlay/Modal');

var _Modal2 = _interopRequireDefault(_Modal);

var _Fade = require('rsuite-utils/lib/Animation/Fade');

var _Fade2 = _interopRequireDefault(_Fade);

var _domLib = require('dom-lib');

var _utils = require('./utils');

var _ModalDialog = require('./ModalDialog');

var _ModalDialog2 = _interopRequireDefault(_ModalDialog);

var _ModalBody = require('./ModalBody');

var _ModalBody2 = _interopRequireDefault(_ModalBody);

var _ModalHeader = require('./ModalHeader');

var _ModalHeader2 = _interopRequireDefault(_ModalHeader);

var _ModalTitle = require('./ModalTitle');

var _ModalTitle2 = _interopRequireDefault(_ModalTitle);

var _ModalFooter = require('./ModalFooter');

var _ModalFooter2 = _interopRequireDefault(_ModalFooter);

var _TypeDefinition = require('./utils/TypeDefinition');

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
/* eslint-disable react/no-find-dom-node */


var TRANSITION_DURATION = 300;
var BACKDROP_TRANSITION_DURATION = 150;

var Modal = function (_React$Component) {
  _inherits(Modal, _React$Component);

  function Modal(props) {
    _classCallCheck(this, Modal);

    var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));

    _this.modal = null;
    _this.dialog = null;
    _this.windowResizeListener = null;

    _this.handleShow = function () {
      _this.windowResizeListener = (0, _domLib.on)(window, 'resize', _this.handleWindowResize);
      _this.setState(_this.getStyles());
      var onEntering = _this.props.onEntering;

      onEntering && onEntering.apply(undefined, arguments);
    };

    _this.handleHide = function () {
      if (_this.windowResizeListener) {
        _this.windowResizeListener.off();
      }
      var onExited = _this.props.onExited;

      onExited && onExited.apply(undefined, arguments);
    };

    _this.handleDialogClick = function (event) {
      if (event.target !== event.currentTarget) {
        return;
      }
      var onHide = _this.props.onHide;

      onHide && onHide(event);
    };

    _this.handleWindowResize = function () {
      _this.setState(_this.getStyles());
    };

    _this.addPrefix = function (name) {
      return (0, _utils.prefix)(_this.props.classPrefix)(name);
    };

    _this.dialogRef = function (ref) {
      _this.dialog = ref;
    };

    _this.modalRef = function (ref) {
      _this.modal = ref;
    };

    _this.state = {
      modalStyles: {},
      bodyStyles: {}
    };
    return _this;
  }

  Modal.prototype.getChildContext = function getChildContext() {
    return {
      onModalHide: this.props.onHide
    };
  };

  Modal.prototype.componentWillUnmount = function componentWillUnmount() {
    if (this.windowResizeListener) {
      this.windowResizeListener.off();
    }
  };

  Modal.prototype.getStyles = function getStyles() {
    var _props = this.props,
        container = _props.container,
        overflow = _props.overflow,
        drawer = _props.drawer;

    var node = (0, _reactDom.findDOMNode)(this.dialog);
    var doc = (0, _domLib.ownerDocument)(node);
    var body = container || doc.body;
    var scrollHeight = node ? node.scrollHeight : 0;

    var bodyIsOverflowing = (0, _domLib.isOverflowing)((0, _reactDom.findDOMNode)(body));
    var modalIsOverflowing = scrollHeight > doc.documentElement.clientHeight;

    var styles = {
      modalStyles: {
        paddingRight: bodyIsOverflowing && !modalIsOverflowing ? (0, _domLib.getScrollbarSize)() : 0,
        paddingLeft: !bodyIsOverflowing && modalIsOverflowing ? (0, _domLib.getScrollbarSize)() : 0
      },
      bodyStyles: {}
    };

    if (overflow) {
      var dialogDOM = (0, _reactDom.findDOMNode)(this.dialog);
      var _bodyStyles = {
        overflow: 'auto'
      };

      // default margin
      var headerHeight = 46;
      var footerHeight = 46;
      var contentHeight = 30;

      var headerDOM = dialogDOM.querySelector('.' + this.addPrefix('header'));
      var footerDOM = dialogDOM.querySelector('.' + this.addPrefix('footer'));
      var contentDOM = dialogDOM.querySelector('.' + this.addPrefix('content'));

      headerHeight = headerDOM ? (0, _domLib.getHeight)(headerDOM) + headerHeight : headerHeight;
      footerHeight = footerDOM ? (0, _domLib.getHeight)(footerDOM) + headerHeight : headerHeight;
      contentHeight = contentDOM ? (0, _domLib.getHeight)(contentDOM) + contentHeight : contentHeight;

      if (drawer) {
        _bodyStyles.height = contentHeight - (headerHeight + footerHeight);
      } else {
        /**
         * Header height + Footer height + Dialog margin
         */
        var excludeHeight = headerHeight + footerHeight + 60;
        var bodyHeight = (0, _domLib.getHeight)(window) - excludeHeight;
        var maxHeight = scrollHeight >= bodyHeight ? bodyHeight : scrollHeight;
        _bodyStyles.maxHeight = maxHeight;
      }

      styles.bodyStyles = _bodyStyles;
    }

    return styles;
  };

  Modal.prototype.render = function render() {
    var _classNames, _classNames2;

    var _props2 = this.props,
        className = _props2.className,
        children = _props2.children,
        dialogClassName = _props2.dialogClassName,
        backdropClassName = _props2.backdropClassName,
        dialogStyle = _props2.dialogStyle,
        overflow = _props2.overflow,
        animation = _props2.animation,
        classPrefix = _props2.classPrefix,
        style = _props2.style,
        show = _props2.show,
        size = _props2.size,
        full = _props2.full,
        dialogComponentClass = _props2.dialogComponentClass,
        rest = _objectWithoutProperties(_props2, ['className', 'children', 'dialogClassName', 'backdropClassName', 'dialogStyle', 'overflow', 'animation', 'classPrefix', 'style', 'show', 'size', 'full', 'dialogComponentClass']);

    var _state = this.state,
        modalStyles = _state.modalStyles,
        bodyStyles = _state.bodyStyles;

    var inClass = { in: show && !animation };
    var Dialog = dialogComponentClass;

    var parentProps = (0, _pick3.default)(rest, _Modal2.default.handledProps);
    var items = null;

    if (children) {
      items = _utils.ReactChildren.mapCloneElement(children, function (child) {
        var displayName = child.type.displayName;
        if (displayName && displayName.indexOf('Body') !== -1) {
          return {
            style: bodyStyles
          };
        }
        return null;
      });
    }

    var classes = (0, _classnames2.default)(this.addPrefix(size), className, (_classNames = {}, _classNames[this.addPrefix('full')] = full, _classNames));

    var modal = React.createElement(
      Dialog,
      _extends({}, (0, _pick3.default)(rest, Object.keys(_ModalDialog2.default.propTypes || {})), {
        style: _extends({}, modalStyles, style),
        classPrefix: classPrefix,
        className: classes,
        dialogClassName: dialogClassName,
        dialogStyle: dialogStyle,
        onClick: rest.backdrop === true ? this.handleDialogClick : null,
        ref: this.dialogRef
      }),
      items
    );

    return React.createElement(
      _Modal2.default,
      _extends({
        ref: this.modalRef,
        show: show,
        onEntering: this.handleShow,
        onExited: this.handleHide,
        backdropClassName: (0, _classnames2.default)(this.addPrefix('backdrop'), backdropClassName, inClass),
        containerClassName: (0, _classnames2.default)(this.addPrefix('open'), (_classNames2 = {}, _classNames2[this.addPrefix('has-backdrop')] = rest.backdrop, _classNames2)),
        transition: animation ? _Fade2.default : undefined,
        dialogTransitionTimeout: TRANSITION_DURATION,
        backdropTransitionTimeout: BACKDROP_TRANSITION_DURATION
      }, parentProps),
      modal
    );
  };

  return Modal;
}(React.Component);

Modal.defaultProps = {
  size: 'sm',
  backdrop: true,
  keyboard: true,
  autoFocus: true,
  enforceFocus: true,
  animation: true,
  dialogComponentClass: _ModalDialog2.default,
  overflow: true
};
Modal.childContextTypes = {
  onModalHide: _propTypes2.default.func
};
Modal.handledProps = ['animation', 'autoFocus', 'backdrop', 'backdropClassName', 'backdropStyle', 'backdropTransitionTimeout', 'children', 'className', 'classPrefix', 'container', 'dialogClassName', 'dialogComponentClass', 'dialogStyle', 'dialogTransitionTimeout', 'drawer', 'enforceFocus', 'full', 'keyboard', 'onBackdropClick', 'onEnter', 'onEntered', 'onEntering', 'onEscapeKeyUp', 'onExit', 'onExited', 'onExiting', 'onHide', 'onRendered', 'onShow', 'overflow', 'show', 'size', 'style', 'transition'];
Modal.propTypes = {
  classPrefix: _propTypes2.default.string.isRequired,
  size: function size() {
    return (typeof _TypeDefinition.bpfrpt_proptype_Size === 'function' ? _TypeDefinition.bpfrpt_proptype_Size.isRequired ? _TypeDefinition.bpfrpt_proptype_Size.isRequired : _TypeDefinition.bpfrpt_proptype_Size : _propTypes2.default.shape(_TypeDefinition.bpfrpt_proptype_Size).isRequired).apply(this, arguments);
  },
  container: _propTypes2.default.oneOfType([function () {
    return (typeof (React.ElementType == null ? {} : React.ElementType) === 'function' ? _propTypes2.default.instanceOf(React.ElementType == null ? {} : React.ElementType) : _propTypes2.default.any).apply(this, arguments);
  }, _propTypes2.default.func]),
  onRendered: _propTypes2.default.func,
  className: _propTypes2.default.string,
  children: _propTypes2.default.node,
  dialogClassName: _propTypes2.default.string,
  backdropClassName: _propTypes2.default.string,
  style: _propTypes2.default.object,
  dialogStyle: _propTypes2.default.object,
  backdropStyle: _propTypes2.default.object,
  show: _propTypes2.default.bool,
  full: _propTypes2.default.bool,
  backdrop: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.oneOf(['static'])]),
  keyboard: _propTypes2.default.bool,
  transition: function transition() {
    return (typeof (React.ElementType == null ? {} : React.ElementType) === 'function' ? _propTypes2.default.instanceOf(React.ElementType == null ? {} : React.ElementType) : _propTypes2.default.any).apply(this, arguments);
  },
  dialogTransitionTimeout: _propTypes2.default.number,
  backdropTransitionTimeout: _propTypes2.default.number,
  autoFocus: _propTypes2.default.bool,
  enforceFocus: _propTypes2.default.bool,
  overflow: _propTypes2.default.bool,
  drawer: _propTypes2.default.bool,
  animation: _propTypes2.default.bool,
  dialogComponentClass: function dialogComponentClass() {
    return (typeof (React.ElementType == null ? {} : React.ElementType) === 'function' ? _propTypes2.default.instanceOf(React.ElementType == null ? {} : React.ElementType).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
  },
  onEscapeKeyUp: _propTypes2.default.func,
  onBackdropClick: _propTypes2.default.func,
  onShow: _propTypes2.default.func,
  onHide: _propTypes2.default.func,
  onEnter: _propTypes2.default.func,
  onEntering: _propTypes2.default.func,
  onEntered: _propTypes2.default.func,
  onExit: _propTypes2.default.func,
  onExiting: _propTypes2.default.func,
  onExited: _propTypes2.default.func
};


var EnhancedModal = (0, _utils.defaultProps)({
  classPrefix: 'modal'
})(Modal);

(0, _setStatic2.default)('Body', _ModalBody2.default)(EnhancedModal);
(0, _setStatic2.default)('Header', _ModalHeader2.default)(EnhancedModal);
(0, _setStatic2.default)('Title', _ModalTitle2.default)(EnhancedModal);
(0, _setStatic2.default)('Footer', _ModalFooter2.default)(EnhancedModal);
(0, _setStatic2.default)('Dialog', _ModalDialog2.default)(EnhancedModal);

exports.default = (0, _setDisplayName2.default)('Modal')(EnhancedModal);