'use strict';

exports.__esModule = true;

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 _react2 = _interopRequireDefault(_react);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _helper = require('./Shared/helper.js');

var _CPortal = require('./CPortal');

var _CPortal2 = _interopRequireDefault(_CPortal);

var _CFade = require('./CFade');

var _CFade2 = _interopRequireDefault(_CFade);

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

function noop() {}

var FadePropTypes = _propTypes2.default.shape(_CFade2.default.propTypes);

//component - CoreUI / CModal

var CModal = function CModal(props) {
  var _useState = (0, _react.useState)(props.show),
      isOpen = _useState[0],
      setIsOpen = _useState[1];

  var fields = (0, _react.useRef)({
    _element: null,
    _originalBodyPadding: null,
    lastProps: {}
  }).current;

  var onOpened = function onOpened(node, isAppearing) {
    props.onOpened();
    (props.modalTransition.onEntered || noop)(node, isAppearing);
  };

  var onClosed = function onClosed(node) {
    props.onClosed();
    (props.modalTransition.onExited || noop)(node);
    destroy();
    if (fields._isMounted) {
      setIsOpen(false);
    }
  };

  var setFocus = function setFocus() {
    if (fields._dialog && fields._dialog.parentNode && typeof fields._dialog.parentNode.focus === 'function') {
      fields._dialog.parentNode.focus();
    }
  };

  var getFocusableChildren = function getFocusableChildren() {
    return fields._element.querySelectorAll(_helper.focusableElements.join(', '));
  };

  var getFocusedChild = function getFocusedChild() {
    var currentFocus = void 0;
    var focusableChildren = getFocusableChildren();
    try {
      currentFocus = document.activeElement;
    } catch (err) {
      currentFocus = focusableChildren[0];
    }
    return currentFocus;
  };

  var handleBackdropClick = function handleBackdropClick(e) {
    if (e.target === fields._mouseDownElement) {
      e.stopPropagation();
      if (!isOpen || props.backdrop !== true) return;
      var backdrop = fields._dialog ? fields._dialog.parentNode : null;
      if (backdrop && e.target === backdrop && props.toggle) {
        props.toggle(e);
      }
    }
  };

  var handleTab = function handleTab(e) {
    if (e.which !== 9) return;
    var focusableChildren = getFocusableChildren();
    var totalFocusable = focusableChildren.length;
    var currentFocus = getFocusedChild();
    var focusedIndex = 0;
    for (var i = 0; i < totalFocusable; i += 1) {
      if (focusableChildren[i] === currentFocus) {
        focusedIndex = i;
        break;
      }
    }
    if (e.shiftKey && focusedIndex === 0) {
      e.preventDefault();
      focusableChildren[totalFocusable - 1].focus();
    } else if (!e.shiftKey && focusedIndex === totalFocusable - 1) {
      e.preventDefault();
      focusableChildren[0].focus();
    }
  };

  var handleBackdropMouseDown = function handleBackdropMouseDown(e) {
    fields._mouseDownElement = e.target;
  };

  var handleEscape = function handleEscape(e) {
    if (props.show && props.keyboard && e.keyCode === 27 && props.toggle) {
      e.preventDefault();
      e.stopPropagation();
      props.toggle(e);
    }
  };

  var init = function init() {
    try {
      fields._triggeringElement = document.activeElement;
    } catch (err) {
      fields._triggeringElement = null;
    }
    fields._element = document.createElement('div');
    fields._element.setAttribute('tabindex', '-1');
    fields._element.style.position = 'relative';
    fields._element.style.zIndex = props.zIndex;
    fields._originalBodyPadding = (0, _helper.getOriginalBodyPadding)();
    (0, _helper.conditionallyUpdateScrollbar)();
    document.body.appendChild(fields._element);
    if (CModal.openCount === 0) {
      document.body.className = (0, _classnames2.default)(document.body.className, (0, _helper.mapToCssModules)('modal-open', props.cssModule));
    }
    CModal.openCount += 1;
  };

  var destroy = function destroy() {
    if (fields._element) {
      document.body.removeChild(fields._element);
      fields._element = null;
    }
    if (fields._triggeringElement) {
      if (fields._triggeringElement.focus) fields._triggeringElement.focus();
      fields._triggeringElement = null;
    }
    if (CModal.openCount <= 1) {
      var modalOpenClassName = (0, _helper.mapToCssModules)('modal-open', props.cssModule);
      var modalOpenClassNameRegex = new RegExp('(^| )' + modalOpenClassName + '( |$)');
      document.body.className = document.body.className.replace(modalOpenClassNameRegex, ' ').trim();
    }
    CModal.openCount -= 1;
    (0, _helper.setScrollbarWidth)(fields._originalBodyPadding);
  };

  var setState = function setState(oVal, nVal, setF) {
    if (nVal === oVal) return;
    setF(nVal);
  };

  // effect

  (0, _react.useEffect)(function () {
    if (props.onEnter) {
      props.onEnter();
    }
    if (isOpen && props.autoFocus) {
      setFocus();
    }
    fields._isMounted = true;
    return function cleanup() {
      if (props.onExit) {
        props.onExit();
      }
      if (isOpen) {
        destroy();
      }
      fields._isMounted = false;
    };
  }, []);

  (0, _react.useEffect)(function () {
    if (props.autoFocus && isOpen && !fields.lastIsOpen) {
      setFocus();
    }
    if (fields._element && fields.lastProps.zIndex !== props.zIndex) {
      fields._element.style.zIndex = props.zIndex;
    }
  }, [isOpen]);

  (0, _react.useEffect)(function () {
    fields.lastProps = _extends({}, props);
    fields.lastIsOpen = isOpen;
    fields.firstRender = false;
  });

  // render

  var renderModalDialog = function renderModalDialog() {
    var _classNames;

    var attributes = (0, _helper.omit)(props, Object.keys(CModal.propTypes));
    var dialogBaseClass = 'modal-dialog';
    return _react2.default.createElement(
      'div',
      _extends({}, attributes, {
        className: (0, _helper.mapToCssModules)((0, _classnames2.default)(dialogBaseClass, props.className, (_classNames = {}, _classNames['modal-' + props.size] = props.size, _classNames[dialogBaseClass + '-centered'] = props.centered, _classNames)), props.cssModule),
        role: 'document',
        ref: function ref(c) {
          fields._dialog = c;
        }
      }),
      _react2.default.createElement(
        'div',
        {
          className: (0, _helper.mapToCssModules)((0, _classnames2.default)('modal-content', props.contentClassName), props.cssModule)
        },
        props.children
      )
    );
  };

  if (props.show && !fields.lastProps.show) {
    setState(isOpen, props.show, setIsOpen);
  }
  if (!fields.firstRender) {
    if (isOpen && !fields.lastIsOpen) {
      init();
    }
  }

  if (isOpen) {
    var cssModule = props.cssModule,
        innerRef = props.innerRef,
        wrapClassName = props.wrapClassName,
        modalClassName = props.modalClassName,
        backdropClassName = props.backdropClassName,
        _isOpen = props.show,
        backdrop = props.backdrop,
        role = props.role,
        labelledBy = props.labelledBy,
        external = props.external;


    var modalAttributes = {
      onClick: handleBackdropClick,
      onMouseDown: handleBackdropMouseDown,
      onKeyUp: handleEscape,
      onKeyDown: handleTab,
      style: { display: 'block' },
      'aria-labelledby': labelledBy,
      role: role,
      tabIndex: '-1'
    };

    var hasTransition = props.fade;

    var modalTransition = _extends({}, _CFade2.default.defaultProps, props.modalTransition, {
      baseClass: hasTransition ? props.modalTransition.baseClass : '',
      timeout: hasTransition ? props.modalTransition.timeout : 0
    });

    var backdropTransition = _extends({}, _CFade2.default.defaultProps, props.backdropTransition, {
      baseClass: hasTransition ? props.backdropTransition.baseClass : '',
      timeout: hasTransition ? props.backdropTransition.timeout : 0
    });

    var Backdrop = backdrop && (hasTransition ? _react2.default.createElement(_CFade2.default, _extends({}, backdropTransition, {
      'in': _isOpen && !!backdrop,
      cssModule: cssModule,
      className: (0, _helper.mapToCssModules)((0, _classnames2.default)('modal-backdrop', backdropClassName), cssModule)
    })) : _react2.default.createElement('div', { className: (0, _helper.mapToCssModules)((0, _classnames2.default)('modal-backdrop', 'show', backdropClassName), cssModule) }));

    return _react2.default.createElement(
      _CPortal2.default,
      { node: fields._element },
      _react2.default.createElement(
        'div',
        { className: (0, _helper.mapToCssModules)(wrapClassName) },
        _react2.default.createElement(
          _CFade2.default,
          _extends({}, modalAttributes, modalTransition, {
            'in': _isOpen,
            onEntered: onOpened,
            onExited: onClosed,
            cssModule: cssModule,
            className: (0, _helper.mapToCssModules)((0, _classnames2.default)('modal', modalClassName), cssModule),
            innerRef: innerRef
          }),
          external,
          renderModalDialog()
        ),
        Backdrop
      )
    );
  }

  return null;
};

CModal.propTypes = process.env.NODE_ENV !== "production" ? {
  children: _propTypes2.default.node,
  className: _propTypes2.default.string,
  cssModule: _propTypes2.default.object,
  //
  innerRef: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.string]),
  show: _propTypes2.default.bool,
  autoFocus: _propTypes2.default.bool,
  centered: _propTypes2.default.bool,
  size: _propTypes2.default.string,
  toggle: _propTypes2.default.func,
  keyboard: _propTypes2.default.bool,
  role: _propTypes2.default.string,
  labelledBy: _propTypes2.default.string,
  backdrop: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.oneOf(['static'])]),
  onEnter: _propTypes2.default.func,
  onExit: _propTypes2.default.func,
  onOpened: _propTypes2.default.func,
  onClosed: _propTypes2.default.func,
  wrapClassName: _propTypes2.default.string,
  modalClassName: _propTypes2.default.string,
  backdropClassName: _propTypes2.default.string,
  contentClassName: _propTypes2.default.string,
  external: _propTypes2.default.node,
  fade: _propTypes2.default.bool,
  zIndex: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
  backdropTransition: FadePropTypes,
  modalTransition: FadePropTypes
} : {};

CModal.defaultProps = {
  show: false,
  autoFocus: true,
  centered: false,
  role: 'dialog',
  backdrop: true,
  keyboard: true,
  zIndex: 1050,
  fade: true,
  onOpened: noop,
  onClosed: noop,
  modalTransition: {
    timeout: _helper.TransitionTimeouts.Modal
  },
  backdropTransition: {
    mountOnEnter: true,
    timeout: _helper.TransitionTimeouts.Fade
  }
};

CModal.openCount = 0;

exports.default = CModal;
module.exports = exports['default'];