import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
import React from 'react';
import FocusLock from 'react-focus-lock';
import throttle from 'lodash.throttle';
import { globalObject } from '@skbkontur/global-object';
import { isNonNullable } from "../../../lib/utils";
import { isKeyEscape } from "../../../lib/events/keyboard/identifiers";
import * as LayoutEvents from "../../../lib/LayoutEvents";
import { RenderContainer } from "../../../internal/RenderContainer";
import { ZIndex } from "../../../internal/ZIndex";
import { stopPropagation } from "../../../lib/events/stopPropagation";
import { HideBodyVerticalScroll } from "../../../internal/HideBodyVerticalScroll";
import { ModalStack } from "../../../lib/ModalStack";
import { ResizeDetector } from "../../../internal/ResizeDetector";
import { ThemeContext } from "../../../lib/theming/ThemeContext";
import { isIE11 } from "../../../lib/client";
import { CommonWrapper } from "../../../internal/CommonWrapper";
import { cx } from "../../../lib/theming/Emotion";
import { createPropsGetter } from "../../../lib/createPropsGetter";
import { ResponsiveLayout } from "../../ResponsiveLayout";
import { isThemeGTE } from "../../../lib/theming/ThemeHelpers";
import { catchUnreachableWarning } from "../../../lib/typeGuards";
import { ModalContext } from "../ModalContext";
import { ModalFooter } from "../ModalFooter";
import { ModalHeader } from "../ModalHeader";
import { ModalBody } from "../ModalBody";
import { ModalClose } from "../ModalClose";
import { styles } from "../Modal.styles";
import { getModalTheme } from "../getModalTheme";
var mountedModalsCount = 0;
export var ModalDataTids = {
  container: 'modal-container',
  content: 'modal-content',
  close: 'modal-close'
};
export var ModalZIndexPriority = {
  Cross: 2,
  Content: 1
};

/** Модальное окно — это эмуляция диалогового окна браузера, оно появляется поверх страницы в ответ на действия пользователя и блокирует доступ к основному содержимому страницы.
 *
 * Составной компонент, включает в себя:
 * - «шапку» [Modal.Header](https://tech.skbkontur.ru/kontur-ui/?path=/docs/react-ui_overlay-modal-modalheader--docs), состоящую из заголовка и крестика закрытия окна;
 * - контент-зону [Modal.Body](https://tech.skbkontur.ru/kontur-ui/?path=/docs/react-ui_overlay-modal-modalbody--docs);
 * - футер [Modal.Footer](https://tech.skbkontur.ru/kontur-ui/?path=/docs/react-ui_overlay-modal-modalfooter--docs).
 */
export var Modal = /*#__PURE__*/function (_React$Component) {
  function Modal() {
    var _this;
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
    _this.getProps = createPropsGetter(Modal.defaultProps);
    _this.state = {
      stackPosition: 0,
      hasBackground: true,
      horizontalScroll: false,
      hasHeader: false,
      hasFooter: false,
      hasPanel: false
    };
    _this.stackSubscription = null;
    _this.containerNode = null;
    _this.mouseDownTarget = null;
    _this.mouseUpTarget = null;
    _this.getMobileContainerClassName = function () {
      var mobileAppearance = _this.getProps().mobileAppearance;
      switch (mobileAppearance) {
        case 'fullscreen-spacing':
          return;
        case 'auto':
          if (_this.state.hasFooter) {
            return;
          }
          return [styles.mobileContainerSmall5_2()];
        case 'fullscreen':
          return [styles.mobileContainerFullscreen5_2()];
        case 'center':
          return [styles.mobileContainerSmall5_2()];
        case 'bottom':
          return [styles.mobileContainerSmall5_2(), styles.mobileContainerSmallBottom5_2()];
        case 'top':
          return [styles.mobileContainerSmall5_2(), styles.mobileContainerSmallTop5_2()];
        default:
          return catchUnreachableWarning(mobileAppearance, false);
      }
    };
    _this.requestClose = function () {
      if (_this.props.disableClose) {
        return;
      }
      if (_this.props.onClose) {
        _this.props.onClose();
      }
    };
    _this.refContainer = function (center) {
      _this.containerNode = center;
    };
    _this.handleStackChange = function (stack) {
      _this.setState({
        stackPosition: stack.indexOf(_this),
        hasBackground: ModalStack.isBlocking(_this)
      });
    };
    _this.handleContainerMouseDown = function (event) {
      _this.mouseDownTarget = event.target;
    };
    _this.handleContainerMouseUp = function (event) {
      _this.mouseUpTarget = event.target;
    };
    _this.handleContainerClick = function (event) {
      if (!_this.props.ignoreBackgroundClick) {
        var target = event.target,
          currentTarget = event.currentTarget;
        if (target === currentTarget && _this.mouseDownTarget === currentTarget && _this.mouseUpTarget === currentTarget) {
          _this.requestClose();
        }
      }
    };
    _this.handleKeyDown = function (e) {
      if (_this.state.stackPosition !== 0) {
        return;
      }
      if (isKeyEscape(e)) {
        stopPropagation(e);
        _this.requestClose();
      }
    };
    _this.checkHorizontalScrollAppearance = function () {
      var hasScroll = false;
      if (_this.containerNode) {
        var containerClientWidth = _this.containerNode.clientWidth;
        var containerScrollWidth = _this.containerNode.scrollWidth;
        hasScroll = containerClientWidth < containerScrollWidth;
      }
      if (hasScroll && !_this.state.horizontalScroll) {
        _this.setState({
          horizontalScroll: true
        });
      } else if (_this.state.horizontalScroll) {
        _this.setState({
          horizontalScroll: false
        });
      }
    };
    _this.throttledCheckHorizontalScroll = throttle(_this.checkHorizontalScrollAppearance, 100);
    _this.handleResize = function () {
      LayoutEvents.emit();
    };
    _this.setHasHeader = function (hasHeader) {
      _this.setState({
        hasHeader: hasHeader
      });
    };
    _this.setHasFooter = function (hasFooter) {
      _this.setState({
        hasFooter: hasFooter
      });
    };
    _this.setHasPanel = function (hasPanel) {
      _this.setState({
        hasPanel: hasPanel
      });
    };
    return _this;
  }
  _inheritsLoose(Modal, _React$Component);
  var _proto = Modal.prototype;
  _proto.componentDidMount = function componentDidMount() {
    this.stackSubscription = ModalStack.add(this, this.handleStackChange);
    if (mountedModalsCount === 0) {
      globalObject.addEventListener == null || globalObject.addEventListener('resize', this.throttledCheckHorizontalScroll);
    }
    mountedModalsCount++;
    globalObject.addEventListener == null || globalObject.addEventListener('keydown', this.handleKeyDown);
    this.checkHorizontalScrollAppearance();
    if (this.containerNode) {
      this.containerNode.addEventListener('scroll', LayoutEvents.emit);
    }
  };
  _proto.componentWillUnmount = function componentWillUnmount() {
    if (--mountedModalsCount === 0) {
      globalObject.removeEventListener == null || globalObject.removeEventListener('resize', this.throttledCheckHorizontalScroll);
      LayoutEvents.emit();
    }
    globalObject.removeEventListener == null || globalObject.removeEventListener('keydown', this.handleKeyDown);
    if (isNonNullable(this.stackSubscription)) {
      this.stackSubscription.remove();
    }
    ModalStack.remove(this);
    if (this.containerNode) {
      this.containerNode.removeEventListener('scroll', LayoutEvents.emit);
    }
  };
  _proto.render = function render() {
    var _this2 = this;
    return /*#__PURE__*/React.createElement(ThemeContext.Consumer, null, function (theme) {
      _this2.theme = getModalTheme(theme, _this2.props.theme);
      return /*#__PURE__*/React.createElement(ThemeContext.Provider, {
        value: _this2.theme
      }, _this2.renderMain());
    });
  };
  _proto.renderMain = function renderMain() {
    var _this3 = this;
    var _this$props = this.props,
      noClose = _this$props.noClose,
      disableClose = _this$props.disableClose,
      width = _this$props.width,
      mobileAppearance = _this$props.mobileAppearance,
      alignTop = _this$props.alignTop,
      children = _this$props.children,
      ariaLabel = _this$props['aria-label'],
      ariaLabelledby = _this$props['aria-labelledby'];
    var _this$state = this.state,
      hasHeader = _this$state.hasHeader,
      hasFooter = _this$state.hasFooter,
      hasPanel = _this$state.hasPanel;
    var _this$getProps = this.getProps(),
      role = _this$getProps.role,
      disableFocusLock = _this$getProps.disableFocusLock;
    var modalContextProps = {
      hasHeader: hasHeader,
      horizontalScroll: this.state.horizontalScroll,
      setHasHeader: this.setHasHeader,
      setHasFooter: this.setHasFooter,
      setHasPanel: this.setHasPanel,
      mobileOnFullScreen: this.props.mobileAppearance === 'fullscreen'
    };
    if (!noClose) {
      modalContextProps.close = {
        disableClose: disableClose,
        requestClose: this.requestClose
      };
    }
    if (!hasFooter || hasPanel) {
      modalContextProps.additionalPadding = true;
    }
    var versionGTE5_2 = isThemeGTE(this.theme, '5.2');
    var style = {};
    var containerStyle = {};
    if (width) {
      style.width = width;
    } else {
      containerStyle.width = 'auto';
    }
    var getMobileCenterContainerClassNames = function getMobileCenterContainerClassNames() {
      if (versionGTE5_2) {
        var _cx;
        return cx(styles.mobileCenterContainer5_2(_this3.theme), (_cx = {}, _cx[styles.mobileCenterContainerBig5_2(_this3.theme)] = mobileAppearance === 'fullscreen-spacing' || mobileAppearance === 'auto' && hasFooter, _cx[styles.mobileCenterContainerFullscreen5_2()] = mobileAppearance === 'fullscreen', _cx));
      }
      return cx(styles.mobileCenterContainer());
    };
    return /*#__PURE__*/React.createElement(RenderContainer, null, /*#__PURE__*/React.createElement(CommonWrapper, this.props, /*#__PURE__*/React.createElement(ZIndex, {
      priority: 'Modal',
      className: styles.root()
    }, /*#__PURE__*/React.createElement(HideBodyVerticalScroll, null), this.state.hasBackground && /*#__PURE__*/React.createElement("div", {
      onMouseDown: this.handleContainerMouseDown,
      onMouseUp: this.handleContainerMouseUp,
      onClick: this.handleContainerClick,
      className: styles.bg(this.theme)
    }), /*#__PURE__*/React.createElement(ResponsiveLayout, null, function (_ref) {
      var _cx2, _cx3, _cx4, _cx5, _cx6;
      var isMobile = _ref.isMobile;
      return /*#__PURE__*/React.createElement("div", {
        "aria-labelledby": ariaLabelledby,
        ref: _this3.refContainer,
        className: cx(styles.container(), versionGTE5_2 && styles.container5_2(), (!versionGTE5_2 || !isMobile) && styles.containerDesktop(), !versionGTE5_2 && isMobile && styles.containerMobile(_this3.theme), versionGTE5_2 && isMobile && _this3.getMobileContainerClassName()),
        onMouseDown: _this3.handleContainerMouseDown,
        onMouseUp: _this3.handleContainerMouseUp,
        onClick: _this3.handleContainerClick,
        "data-tid": ModalDataTids.container
      }, /*#__PURE__*/React.createElement("div", {
        "aria-modal": true,
        "aria-label": ariaLabel,
        role: role,
        className: cx((_cx2 = {}, _cx2[styles.centerContainer()] = true, _cx2[getMobileCenterContainerClassNames()] = isMobile, _cx2[styles.alignTop()] = Boolean(alignTop), _cx2)),
        style: isMobile ? undefined : containerStyle,
        "data-tid": ModalDataTids.content
      }, /*#__PURE__*/React.createElement("div", {
        className: cx((_cx3 = {}, _cx3[styles.window(_this3.theme)] = true, _cx3[styles.mobileWindow()] = isMobile, _cx3[styles.mobileWindowFullscreen5_2()] = versionGTE5_2 && isMobile && mobileAppearance === 'fullscreen', _cx3)),
        style: isMobile ? undefined : style
      }, /*#__PURE__*/React.createElement(ResizeDetector, {
        onResize: _this3.handleResize,
        fullHeight: isMobile
      }, /*#__PURE__*/React.createElement(FocusLock, {
        disabled: disableFocusLock,
        autoFocus: false,
        className: cx((_cx4 = {}, _cx4[styles.columnFlexContainer()] = isMobile, _cx4), 'focus-lock-container')
      }, !hasHeader && !noClose && /*#__PURE__*/React.createElement(ZIndex, {
        priority: ModalZIndexPriority.Cross,
        className: cx((_cx5 = {}, _cx5[styles.closeWrapper(_this3.theme)] = true, _cx5[styles.mobileCloseWrapper(_this3.theme)] = isMobile, _cx5[styles.mobileCloseWrapper5_2(_this3.theme)] = versionGTE5_2 && isMobile, _cx5))
      }, /*#__PURE__*/React.createElement(ModalClose, {
        className: cx((_cx6 = {}, _cx6[styles.mobileCloseWithoutHeader()] = isMobile && !_this3.state.hasHeader, _cx6[styles.mobileCloseWithoutHeader5_2(_this3.theme)] = versionGTE5_2 && isMobile && !_this3.state.hasHeader, _cx6)),
        requestClose: _this3.requestClose,
        disableClose: disableClose
      })), /*#__PURE__*/React.createElement(ModalContext.Provider, {
        value: modalContextProps
      }, children))))));
    }))));
  };
  return Modal;
}(React.Component);
Modal.__KONTUR_REACT_UI__ = 'Modal';
Modal.displayName = 'Modal';
Modal.Header = ModalHeader;
Modal.Body = ModalBody;
Modal.Footer = ModalFooter;
Modal.defaultProps = {
  // NOTE: в ie нормально не работает
  disableFocusLock: isIE11,
  role: 'dialog',
  mobileAppearance: 'auto'
};