import _extends from "@babel/runtime/helpers/esm/extends";
import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
var _class, _Toast;
import React from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { globalObject } from '@skbkontur/global-object';
import { ThemeFactory } from "../../../lib/theming/ThemeFactory";
import { ThemeContext } from "../../../lib/theming/ThemeContext";
import { RenderContainer } from "../../../internal/RenderContainer";
import { CommonWrapper } from "../../../internal/CommonWrapper";
import { isTestEnv } from "../../../lib/currentEnvironment";
import { rootNode } from "../../../lib/rootNode";
import { styles } from "../Toast.styles";
import { ToastView } from "../ToastView";
import { ToastStatic } from "../ToastStatic";

/**
 * Состояния тоста:
 *
 * - default стиль для отображения по-умолчанию
 * - error стиль для отображения ошибок
 **/

/** @deprecated выпилить старый подход к api push Toast-а в react-ui 6.0 */

/** Объект с конфигурацией отображения Toast-а */

/** TODO: Новый Api для метода push в Toast. Станет api по-умолчанию с версии 6.0. В мажоре нужно будет убрать New из названия */

export var ToastDataTids = {
  toastStatic: 'StaticToast',
  toastView: 'ToastView__root',
  action: 'ToastView__action',
  close: 'ToastView__close'
};

/**
 * `Toast` — это короткое немодальное уведомление, которое сообщает пользователю о результате выполнения его команды.
 * Результат может быть положительным, отрицательным или нейтральным.
 *
 * Доступен статический метод: `Toast.push(notification, action?, showTime?)`.
 * Однако, при его использовании не работает кастомизация и могут быть проблемы с перекрытием уведомления другими элементами страницы.
 *
 * В обозримом будущем планируем **полностью избавиться** от статического метода в компоненте `Toast`.
 *
 * В качестве альтернативы для `Toast.push` мы рекомендуем использовать компонент `SingleToast` или вызов метода push через `ref`.
 *
 * Метод `push` через ref поддерживает два api.
 *
 * 1. Устаревший с последовательной передачей аргументов: `toastRef.current.push('Hi', { label: 'Cancel', handler: () => {} }, 15000)`
 * 2. Новый с передачей объекта конфигурации: `toastRef.current.push('Hi', { action: { label: 'Cancel', handler: () => {} }, showTime: 15000 })`
 *
 * Устаревший подход с передачей аргументов последовательным образом **будет удалён** в следующей мажорной версии.
 */
export var Toast = rootNode(_class = (_Toast = /*#__PURE__*/function (_React$Component) {
  function Toast(props) {
    var _this;
    _this = _React$Component.call(this, props) || this;
    _this.rootRef = /*#__PURE__*/React.createRef();

    /**
     * @public
     */
    _this.close = function () {
      safelyCall(_this.props.onClose, _this.state.notification, _this.state.action);
      _this.setState({
        notification: null,
        action: null
      });
    };
    _this.setRootRef = function (element) {
      _this.setRootNode(element);
      // @ts-expect-error: See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065.
      _this.rootRef.current = element;
    };
    _this._clearTimer = function () {
      if (_this._timeout) {
        globalObject.clearTimeout(_this._timeout);
        _this._timeout = null;
      }
    };
    _this._setTimer = function () {
      var _this$state$showTime;
      _this._clearTimer();
      var showTime = _this.state.action ? 7000 : 3000;
      showTime = (_this$state$showTime = _this.state.showTime) != null ? _this$state$showTime : showTime;
      _this._timeout = globalObject.setTimeout(_this.close, showTime);
    };
    _this._refToast = function (element) {
      _this._toast = element;
    };
    _this.state = {
      notification: null,
      action: null,
      id: 0,
      showTime: null,
      showCloseIcon: false,
      currentUse: 'default'
    };
    return _this;
  }
  _inheritsLoose(Toast, _React$Component);
  var _proto = Toast.prototype;
  _proto.componentWillUnmount = function componentWillUnmount() {
    this._clearTimer();
  };
  _proto.render = function render() {
    var _this2 = this;
    return /*#__PURE__*/React.createElement(ThemeContext.Consumer, null, function (theme) {
      _this2.theme = _this2.props.theme ? ThemeFactory.create(_this2.props.theme, theme) : theme;
      return /*#__PURE__*/React.createElement(ThemeContext.Provider, {
        value: _this2.theme
      }, /*#__PURE__*/React.createElement(RenderContainer, null, /*#__PURE__*/React.createElement(TransitionGroup, null, _this2._renderToast())));
    });
  } /**
    * Показывает тост с `notification` в качестве сообщения.
    * Тост автоматически скрывается через 3 или 7 секунд,
    * в зависимости от наличия у него кнопки `action` внутри config-а.
    * Время показа можно задать вручную, передав `showTime` внутри config-а.
    *
    * @public
    * @param {React.ReactNode} notification
    * @param {ToastPushConfig} config объект с конфигурацией отображения компонента Toast
    *
    * @description Сейчас есть поддержка старого api метода push с передачей аргументов последовательно, но с версии 6.0 этот функционал будет удалён.
    * @example
    * // Будет удален в 6.0
    * push('notification', { label: "cat meow", handler: () => {} }, 15_000, false, "error")
    *
    * @example
    * // Останется в > 6.0
    * push('notification', { action: { label: "cat meow", handler: () => {} }, showTime: 15_000, showCloseIcon: false, use: "error" })
    */;
  _proto.push = function push(notification, configOrAction, showTime, showCloseIcon, use) {
    if (this.state.notification) {
      this.close();
    }
    if (isNewToastPushApi(configOrAction)) {
      var _action = configOrAction.action,
        _showTime = configOrAction.showTime,
        _showCloseIcon = configOrAction.showCloseIcon,
        _use = configOrAction.use;
      safelyCall(this.props.onPush, notification, _action);
      this.setState(function (_ref) {
        var id = _ref.id;
        return {
          notification: notification,
          action: _action,
          id: id + 1,
          showTime: _showTime,
          showCloseIcon: _showCloseIcon,
          currentUse: _use != null ? _use : 'default'
        };
      }, this._setTimer);
    } /** @deprecated выпилить старый подход к api push Toast-а в react-ui 6.0 */
    if (isOldToastPushApi(configOrAction) || isEmptySecondArg(configOrAction)) {
      var _action2 = configOrAction;
      safelyCall(this.props.onPush, notification, _action2);
      this.setState(function (_ref2) {
        var id = _ref2.id;
        return {
          notification: notification,
          action: _action2,
          id: id + 1,
          showTime: showTime,
          showCloseIcon: showCloseIcon,
          currentUse: use != null ? use : 'default'
        };
      }, this._setTimer);
    }
  };
  _proto._renderToast = function _renderToast() {
    var _this$state = this.state,
      notification = _this$state.notification,
      action = _this$state.action,
      id = _this$state.id,
      showCloseIcon = _this$state.showCloseIcon,
      currentUse = _this$state.currentUse;
    if (!notification) {
      return null;
    }
    var toastProps = {
      onMouseEnter: this._clearTimer,
      onMouseLeave: this._setTimer,
      onClose: this.close,
      children: notification,
      'aria-label': this.props['aria-label'],
      action: action,
      showCloseIcon: showCloseIcon,
      use: currentUse
    };
    return /*#__PURE__*/React.createElement(CSSTransition, {
      key: id,
      classNames: {
        enter: styles.enter(),
        enterActive: styles.enterActive(),
        exit: styles.exit(),
        exitActive: styles.exitActive()
      },
      timeout: {
        enter: 200,
        exit: 150
      },
      enter: !isTestEnv,
      exit: !isTestEnv,
      nodeRef: this.rootRef
    }, /*#__PURE__*/React.createElement(CommonWrapper, _extends({
      rootNodeRef: this.setRootRef
    }, this.props), /*#__PURE__*/React.createElement(ToastView, _extends({
      ref: this._refToast
    }, toastProps))));
  };
  return Toast;
}(React.Component), _Toast.__KONTUR_REACT_UI__ = 'Toast', _Toast.displayName = 'Toast', _Toast.push = function (notification, action, showTime, showCloseIcon) {
  ToastStatic.push(notification, action, showTime, showCloseIcon);
}, _Toast.close = function () {
  ToastStatic.close();
}, _Toast)) || _class;
function safelyCall(fn) {
  if (fn) {
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }
    fn.apply(void 0, args);
  }
}
export function isNewToastPushApi(value) {
  return Boolean(value && typeof value === 'object' && !('label' in value));
}
export function isOldToastPushApi(value) {
  return Boolean(value && typeof value === 'object' && 'label' in value);
} /** Хелпер для случая, когда передаём только текст */
export function isEmptySecondArg(value) {
  return !value;
}