import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
var _excluded = ["width", "error", "warning", "size", "autoResize", "resize", "onCut", "onPaste", "maxRows", "onFocus", "selectAllOnFocus", "placeholder", "onValueChange", "showLengthCounter", "lengthCounter", "counterHelp", "extraRow", "disableAnimations", "disabled"];
var _class, _Textarea;
import React from 'react';
import throttle from 'lodash.throttle';
import { globalObject } from '@skbkontur/global-object';
import { isKeyEnter } from "../../../lib/events/keyboard/identifiers";
import { needsPolyfillPlaceholder } from "../../../lib/needsPolyfillPlaceholder";
import * as LayoutEvents from "../../../lib/LayoutEvents";
import { ThemeContext } from "../../../lib/theming/ThemeContext";
import { RenderLayer } from "../../../internal/RenderLayer";
import { ResizeDetector } from "../../../internal/ResizeDetector";
import { isIE11, isSafariWithTextareaBug } from "../../../lib/client";
import { CommonWrapper } from "../../../internal/CommonWrapper";
import { isTestEnv } from "../../../lib/currentEnvironment";
import { cx } from "../../../lib/theming/Emotion";
import { rootNode } from "../../../lib/rootNode";
import { createPropsGetter } from "../../../lib/createPropsGetter";
import { withSize } from "../../../lib/size/SizeDecorator";
import { ReactUIFeatureFlagsContext } from "../../../lib/featureFlagsContext/ReactUIFeatureFlagsContext";
import { getFullReactUIFlagsContext } from "../../../lib/featureFlagsContext/FeatureFlagsHelpers";
import { getTextAreaHeight } from "../TextareaHelpers";
import { styles } from "../Textarea.styles";
import { TextareaCounter } from "../TextareaCounter";
import { TextareaWithSafari17Workaround } from "../TextareaWithSafari17Workaround";
export var DEFAULT_WIDTH = 250;
var AUTORESIZE_THROTTLE_DEFAULT_WAIT = 100;
export var TextareaDataTids = {
  root: 'Textarea__root',
  counter: 'TextareaCounter__root',
  helpIcon: 'TextareaCounter__helpIcon'
};

/**
 * Многострочное поле — это поле ввода, в котором текст отображается в несколько строк.
 */

export var Textarea = rootNode(_class = withSize(_class = (_Textarea = /*#__PURE__*/function (_React$Component) {
  function Textarea() {
    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.clear = function () {
      if (_this.node) {
        _this.node.value = '';
      }
      if (_this.fakeNode) {
        _this.fakeNode.value = '';
      }
    };
    _this.getProps = createPropsGetter(Textarea.defaultProps);
    _this.state = {
      needsPolyfillPlaceholder: needsPolyfillPlaceholder,
      isCounterVisible: false
    };
    _this.reflowCounter = function () {
      if (_this.counter) {
        _this.counter.reflow();
      }
    };
    _this.selectAllId = null;
    _this.textareaObserver = globalObject.MutationObserver ? new globalObject.MutationObserver(_this.reflowCounter) : null;

    /**
     * @public
     * @param {number} start
     * @param {number} end
     */
    _this.setSelectionRange = function (start, end) {
      var _globalObject$documen;
      if (!_this.node) {
        throw new Error('Cannot call "setSelectionRange" on unmounted Input');
      }
      if (((_globalObject$documen = globalObject.document) == null ? void 0 : _globalObject$documen.activeElement) !== _this.node) {
        _this.focus();
      }
      _this.node.setSelectionRange(start, end);
    };

    /** Переводит фокус в поле (если ещё не в фокусе) и выделяет весь текст в нём.
     * Работает с типами `text`, `password`, `tel`, `search`, `url`.
     * @public
     */
    _this.selectAll = function () {
      if (_this.node) {
        _this.setSelectionRange(0, _this.node.value.length);
      }
    };
    _this.delaySelectAll = function () {
      var _globalObject$request;
      return _this.selectAllId = (_globalObject$request = globalObject.requestAnimationFrame == null ? void 0 : globalObject.requestAnimationFrame(_this.selectAll)) != null ? _globalObject$request : null;
    };
    _this.cancelDelayedSelectAll = function () {
      if (_this.selectAllId) {
        globalObject.cancelAnimationFrame == null || globalObject.cancelAnimationFrame(_this.selectAllId);
        _this.selectAllId = null;
      }
    };
    _this.renderMain = function (props) {
      var _cx, _ref, _textareaProps$maxLen, _cx2;
      var _props$width = props.width,
        width = _props$width === void 0 ? DEFAULT_WIDTH : _props$width,
        error = props.error,
        warning = props.warning,
        size = props.size,
        autoResize = props.autoResize,
        resize = props.resize,
        onCut = props.onCut,
        onPaste = props.onPaste,
        maxRows = props.maxRows,
        onFocus = props.onFocus,
        selectAllOnFocus = props.selectAllOnFocus,
        placeholder = props.placeholder,
        onValueChange = props.onValueChange,
        showLengthCounter = props.showLengthCounter,
        lengthCounter = props.lengthCounter,
        counterHelp = props.counterHelp,
        extraRow = props.extraRow,
        disableAnimations = props.disableAnimations,
        disabled = props.disabled,
        textareaProps = _objectWithoutPropertiesLoose(props, _excluded);
      var isCounterVisible = _this.state.isCounterVisible;
      var rootProps = {
        style: {
          width: width
        }
      };
      var textareaClassNames = cx(_this.getTextareaSizeClassName(), (_cx = {}, _cx[styles.textarea(_this.theme)] = true, _cx[styles.hovering(_this.theme)] = !error && !warning, _cx[styles.disabled(_this.theme)] = disabled, _cx[styles.error(_this.theme)] = !!error, _cx[styles.warning(_this.theme)] = !!warning, _cx[styles.disableAnimations()] = _this.isAnimationsDisabled(), _cx));
      var textareaStyle = {
        resize: autoResize ? 'none' : resize,
        textAlign: _this.props.align
      };
      var placeholderPolyfill = null;
      if (_this.state.needsPolyfillPlaceholder && !textareaProps.value && !textareaProps.defaultValue) {
        placeholderPolyfill = /*#__PURE__*/React.createElement("span", {
          className: styles.placeholder()
        }, placeholder);
      }
      var fakeTextarea = null;
      if (autoResize) {
        var fakeProps = {
          value: _this.props.value,
          defaultValue: _this.props.defaultValue,
          className: cx(textareaClassNames, styles.fake()),
          readOnly: true
        };
        fakeTextarea = /*#__PURE__*/React.createElement("textarea", _extends({}, fakeProps, {
          ref: _this.refFake
        }));
      }
      var counter = showLengthCounter && isCounterVisible && _this.node && /*#__PURE__*/
      React.createElement(TextareaCounter, {
        textarea: _this.node,
        size: _this.size,
        help: counterHelp,
        value: textareaProps.value,
        length: (_ref = (_textareaProps$maxLen = textareaProps.maxLength) != null ? _textareaProps$maxLen : lengthCounter) != null ? _ref : 0,
        onCloseHelp: _this.handleCloseCounterHelp,
        ref: _this.refCounter
      });
      var Component = isSafariWithTextareaBug ? TextareaWithSafari17Workaround : 'textarea';
      return /*#__PURE__*/(
        React.createElement(RenderLayer, {
          onFocusOutside: _this.handleCloseCounterHelp,
          onClickOutside: _this.handleCloseCounterHelp,
          active: _this.state.isCounterVisible
        }, /*#__PURE__*/

        React.createElement("label", _extends({
          "data-tid": TextareaDataTids.root
        }, rootProps, {
          className: cx(_this.getRootSizeClassName(), (_cx2 = {}, _cx2[styles.root()] = true, _cx2))
        }), placeholderPolyfill, /*#__PURE__*/
        React.createElement(ResizeDetector, {
          onResize: _this.reflowCounter,
          alignBaseline: _this.featureFlags.textareaBaselineAlign
        }, /*#__PURE__*/
        React.createElement(Component, _extends({}, textareaProps, {
          className: textareaClassNames,
          style: textareaStyle,
          placeholder: !placeholderPolyfill ? placeholder : undefined,
          ref: _this.ref,
          onChange: _this.handleChange,
          onCut: _this.handleCut,
          onPaste: _this.handlePaste,
          onFocus: _this.handleFocus,
          onKeyDown: _this.handleKeyDown,
          disabled: disabled
        }), _this.props.children)), fakeTextarea, counter))
      );
    };
    _this.handleCloseCounterHelp = function () {
      return _this.setState({
        isCounterVisible: false
      });
    };
    _this.handleKeyDown = function (e) {
      // Edge bug: textarea maxlength doesn't work after new line
      // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18833616/
      var value = _this.props.value !== undefined ? _this.props.value.toString() : null;
      var isBlockEnter = isKeyEnter(e) && value !== null && value.length === _this.props.maxLength;
      if (isBlockEnter) {
        e.preventDefault();
      }
      if (_this.props.onKeyDown) {
        _this.props.onKeyDown(e);
      }
    };
    _this.handleChange = function (e) {
      if (needsPolyfillPlaceholder) {
        var fieldIsEmpty = e.target.value === '';
        if (_this.state.needsPolyfillPlaceholder !== fieldIsEmpty) {
          _this.setState({
            needsPolyfillPlaceholder: fieldIsEmpty
          });
        }
      }
      if (_this.props.onValueChange) {
        _this.props.onValueChange(e.target.value);
      }
      if (_this.props.autoResize) {
        _this.autoResize();
      }
      if (_this.props.onChange) {
        _this.props.onChange(e);
      }
      _this.reflowCounter();
    };
    _this.ref = function (element) {
      _this.node = element;
    };
    _this.refFake = function (element) {
      _this.fakeNode = element;
    };
    _this.refCounter = function (ref) {
      _this.counter = ref;
    };
    _this.autoResizeHandler = function () {
      var fakeNode = _this.fakeNode;
      if (!fakeNode) {
        return;
      }
      var node = _this.node;
      if (!node) {
        return;
      }
      if (_this.props.value === undefined) {
        fakeNode.value = node.value;
      }
      var _this$getProps = _this.getProps(),
        rows = _this$getProps.rows,
        maxRows = _this$getProps.maxRows;
      if (rows === undefined || maxRows === undefined) {
        return;
      }
      var _ref2 = getTextAreaHeight({
          node: fakeNode,
          minRows: typeof rows === 'number' ? rows : parseInt(rows, 10),
          maxRows: typeof maxRows === 'number' ? maxRows : parseInt(maxRows, 10),
          extraRow: _this.getProps().extraRow
        }) || {},
        height = _ref2.height,
        exceededMaxHeight = _ref2.exceededMaxHeight;
      if (height === undefined || exceededMaxHeight === undefined) {
        return;
      }
      node.style.height = height + 'px';
      node.style.overflowY = exceededMaxHeight ? 'scroll' : 'hidden';
      fakeNode.style.overflowY = exceededMaxHeight ? 'scroll' : 'hidden';
    };
    _this.autoResize = throttle(_this.autoResizeHandler, _this.getAutoResizeThrottleWait());
    _this.handleCut = function (event) {
      if (_this.props.autoResize) {
        _this.autoResize();
      }
      if (_this.props.onCut) {
        _this.props.onCut(event);
      }
      _this.reflowCounter();
    };
    _this.handlePaste = function (event) {
      if (_this.props.autoResize) {
        _this.autoResize();
      }
      if (_this.props.onPaste) {
        _this.props.onPaste(event);
      }
      _this.reflowCounter();
    };
    _this.handleFocus = function (event) {
      _this.setState({
        isCounterVisible: true
      });
      if (_this.props.selectAllOnFocus) {
        // https://github.com/facebook/react/issues/7769
        _this.node && !isIE11 ? _this.selectAll() : _this.delaySelectAll();
      }
      if (_this.props.onFocus) {
        _this.props.onFocus(event);
      }
    };
    return _this;
  }
  _inheritsLoose(Textarea, _React$Component);
  var _proto = Textarea.prototype;
  _proto.getRootSizeClassName = function getRootSizeClassName() {
    switch (this.size) {
      case 'large':
        return styles.rootLarge(this.theme);
      case 'medium':
        return styles.rootMedium(this.theme);
      case 'small':
      default:
        return styles.rootSmall(this.theme);
    }
  };
  _proto.getTextareaSizeClassName = function getTextareaSizeClassName() {
    switch (this.size) {
      case 'large':
        return styles.textareaLarge(this.theme);
      case 'medium':
        return styles.textareaMedium(this.theme);
      case 'small':
      default:
        return styles.textareaSmall(this.theme);
    }
  };
  _proto.getAutoResizeThrottleWait = function getAutoResizeThrottleWait(props) {
    if (props === void 0) {
      props = this.props;
    } // NOTE: При отключении анимации остается эффект дергания при авто-ресайзе из-за троттлинга расчета высоты
    // Поэтому выставляем таймаут троттла в ноль. Подробности - https://github.com/skbkontur/retail-ui/issues/2120
    return this.isAnimationsDisabled(props) ? 0 : AUTORESIZE_THROTTLE_DEFAULT_WAIT;
  };
  _proto.isAnimationsDisabled = function isAnimationsDisabled(_temp) {
    var _ref3 = _temp === void 0 ? this.props : _temp,
      disableAnimations = _ref3.disableAnimations,
      extraRow = _ref3.extraRow;
    return disableAnimations || !extraRow;
  };
  _proto.componentDidMount = function componentDidMount() {
    if (this.props.autoResize) {
      this.autoResize();
      this.layoutEvents = LayoutEvents.addListener(this.autoResize);
    }
    if (this.node && this.props.showLengthCounter && this.textareaObserver) {
      this.textareaObserver.observe(this.node, {
        attributes: true
      });
    }
  };
  _proto.componentWillUnmount = function componentWillUnmount() {
    if (this.layoutEvents) {
      this.layoutEvents.remove();
    }
    if (this.props.showLengthCounter && this.textareaObserver) {
      this.textareaObserver.disconnect();
    }
    this.cancelDelayedSelectAll();
  };
  _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
    if (this.getAutoResizeThrottleWait() !== this.getAutoResizeThrottleWait(prevProps)) {
      this.autoResize.cancel();
      this.autoResize = throttle(this.autoResizeHandler, this.getAutoResizeThrottleWait());
    }
    var _this$getProps2 = this.getProps(),
      rows = _this$getProps2.rows,
      maxRows = _this$getProps2.maxRows;
    if (this.props.autoResize && (rows !== prevProps.rows || maxRows !== prevProps.maxRows || this.props.value !== prevProps.value)) {
      this.autoResize();
    }
  };
  _proto.render = function render() {
    var _this2 = this;
    return /*#__PURE__*/React.createElement(ReactUIFeatureFlagsContext.Consumer, null, function (flags) {
      _this2.featureFlags = getFullReactUIFlagsContext(flags);
      return /*#__PURE__*/React.createElement(ThemeContext.Consumer, null, function (theme) {
        _this2.theme = theme;
        return /*#__PURE__*/React.createElement(CommonWrapper, _extends({
          rootNodeRef: _this2.setRootNode
        }, _this2.getProps()), _this2.renderMain);
      });
    });
  } /** Программно устанавливает фокус на поле.
    * @public
    */;
  _proto.focus = function focus() {
    if (this.node) {
      this.node.focus();
    }
  } /** Программно снимает фокус с поля.
    * @public
    */;
  _proto.blur = function blur() {
    if (this.node) {
      this.node.blur();
    }
  } /** start - инициирует последовательное изменение числового значения: начинает повторяющееся увеличение/уменьшение, обычно используется при удерживании кнопки «+» или «−» для числового Input. end - останавливает ранее запущенное числоизменение, инициируемое numberStart.
    * [Документация](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange)
    * @public
    */;
  _proto.getNode = function getNode() {
    return this.node;
  };
  return Textarea;
}(React.Component), _Textarea.__KONTUR_REACT_UI__ = 'Textarea', _Textarea.displayName = 'Textarea', _Textarea.defaultProps = {
  rows: 3,
  maxRows: 15,
  extraRow: true,
  disableAnimations: isTestEnv
}, _Textarea)) || _class) || _class;