import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, extends as _extends } from '../../../../_virtual/_rollupPluginBabelHelpers.js';
import React__default, { forwardRef, useState, useRef, useEffect } from 'react';
import { cx } from '../../../../utils/index.js';
import { keyCodes } from '../../../../utils/constants.js';
import { defaultCharacterWidth, excludingNumberSchema, numberSchema, getPreciseValue } from '../../utils/index.js';
import { classes } from '../../NumberInput.tokens.js';
import { InputWrapper, TextWrapper, AdditionalText, Loader, StyledSpinner, DynamicInput, Input, InputWidthHelper } from './Input.styles.js';
import { useForkRef } from '../../../../hooks/useForkRef.js';
import { useDidMountEffect } from '../../../../hooks/useDidMountEffect.js';
import { isNumber } from '../../../../utils/isNumber.js';

var _StyledSpinner;
var _excluded = ["value", "precision", "min", "max", "isLoading", "loader", "disabled", "segmentation", "textBefore", "textAfter", "isManualInput", "isInputFocused", "setIsInputFocused", "setIsAnimationRun", "setInnerValue", "onChange", "onBlur", "onKeyDown", "onDecrementKey", "onIncrementKey", "shouldFocusInput", "onFocusHandled"];
var NumberInput = /*#__PURE__*/forwardRef(function (_ref, ref) {
  var value = _ref.value,
    precision = _ref.precision,
    min = _ref.min,
    max = _ref.max,
    isLoading = _ref.isLoading,
    loader = _ref.loader,
    disabled = _ref.disabled,
    segmentation = _ref.segmentation,
    textBefore = _ref.textBefore,
    textAfter = _ref.textAfter,
    isManualInput = _ref.isManualInput,
    isInputFocused = _ref.isInputFocused,
    setIsInputFocused = _ref.setIsInputFocused,
    setIsAnimationRun = _ref.setIsAnimationRun,
    setInnerValue = _ref.setInnerValue,
    onChange = _ref.onChange,
    onBlur = _ref.onBlur,
    onKeyDown = _ref.onKeyDown,
    onDecrementKey = _ref.onDecrementKey,
    onIncrementKey = _ref.onIncrementKey,
    shouldFocusInput = _ref.shouldFocusInput,
    onFocusHandled = _ref.onFocusHandled,
    rest = _objectWithoutProperties(_ref, _excluded);
  var _useState = useState(value ? "".concat(String(value).length, "ch") : defaultCharacterWidth),
    _useState2 = _slicedToArray(_useState, 2),
    dynamicWidth = _useState2[0],
    setDynamicWidth = _useState2[1];
  var _useState3 = useState(value),
    _useState4 = _slicedToArray(_useState3, 2),
    lastValidValue = _useState4[0],
    setLastValidValue = _useState4[1];
  var _useState5 = useState(undefined),
    _useState6 = _slicedToArray(_useState5, 2),
    errorClass = _useState6[0],
    setErrorClass = _useState6[1];
  var _useState7 = useState(),
    _useState8 = _slicedToArray(_useState7, 2),
    errorValue = _useState8[0],
    setErrorValue = _useState8[1];
  var inputHelperRef = useRef(null);
  var wrapperRef = useRef(null);
  var textWrapperRef = useRef(null);
  var inputRef = useRef(null);
  var inputForkRef = useForkRef(inputRef, ref);
  var solidViewClass = segmentation === 'solid' ? classes.solidView : undefined;
  var manualInputClass = isManualInput ? classes.manualInput : undefined;
  var getInputWidth = function getInputWidth() {
    var _inputHelperRef$curre;
    var firstRender = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
    if (!firstRender && (_inputHelperRef$curre = inputHelperRef.current) !== null && _inputHelperRef$curre !== void 0 && _inputHelperRef$curre.clientWidth) {
      var _inputHelperRef$curre2;
      return "".concat((_inputHelperRef$curre2 = inputHelperRef.current) === null || _inputHelperRef$curre2 === void 0 ? void 0 : _inputHelperRef$curre2.clientWidth, "px");
    }
    if (value) {
      return "".concat(String(value).length, "ch");
    }
    return defaultCharacterWidth;
  };
  var setValues = function setValues(event, newValue) {
    setLastValidValue(newValue);
    setInnerValue(newValue);
    if (onChange) {
      onChange(event, newValue);
    }
  };
  var validateValue = function validateValue(newValue) {
    if (!(newValue !== null && newValue !== void 0 && newValue.toString()) || !isNumber(newValue)) {
      setValues(null, '');
      setIsAnimationRun(false);
      return;
    }
    var resValue = Number(newValue);
    if (max !== undefined && resValue > max) {
      setErrorClass(classes.errorAnimation);
      setErrorValue(max);
      setIsAnimationRun(true);
      return;
    }
    if (min !== undefined && resValue < min) {
      setErrorClass(classes.errorAnimation);
      setErrorValue(min);
      setIsAnimationRun(true);
      return;
    }
    if (String(newValue).endsWith('.')) {
      setValues(null, Number(newValue));
      setIsAnimationRun(false);
      return;
    }
    if (precision !== undefined) {
      var preciseNewValue = Number(getPreciseValue(newValue, precision));
      setValues(null, preciseNewValue);
    }
    setIsAnimationRun(false);
  };
  var handleManualInputChange = function handleManualInputChange(event) {
    var _textWrapperRef$curre, _wrapperRef$current;
    if (!isManualInput || disabled) {
      return;
    }
    setIsAnimationRun(true);
    var newValue = event.target.value;
    if (!isNumber(lastValidValue) && lastValidValue !== '' && !newValue) {
      return;
    }
    if (!newValue) {
      setInnerValue('');
      if (onChange) {
        onChange(event, '');
      }
      return;
    }
    var cleanValue = newValue.replace(excludingNumberSchema, '');
    if (cleanValue.endsWith('.') || cleanValue === '-') {
      setInnerValue(cleanValue);
      if (onChange) {
        onChange(event, cleanValue);
      }
      return;
    }
    var isValid = numberSchema.test(cleanValue);
    if (!isValid) {
      setValues(event, lastValidValue);
      return;
    }
    if (textWrapperRef !== null && textWrapperRef !== void 0 && textWrapperRef.current && wrapperRef !== null && wrapperRef !== void 0 && wrapperRef.current && (textWrapperRef === null || textWrapperRef === void 0 || (_textWrapperRef$curre = textWrapperRef.current) === null || _textWrapperRef$curre === void 0 ? void 0 : _textWrapperRef$curre.clientWidth) > (wrapperRef === null || wrapperRef === void 0 || (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.clientWidth)) {
      wrapperRef.current.scrollLeft = textWrapperRef.current.offsetWidth - textWrapperRef.current.offsetLeft || 0;
    }
    setValues(event, cleanValue);
  };
  var handleClickInputWrapper = function handleClickInputWrapper() {
    if (!isManualInput || !inputRef.current) {
      return;
    }
    if (!isInputFocused) {
      inputRef.current.focus();
    }
    setIsInputFocused(true);
  };
  var handleBlur = function handleBlur(event) {
    validateValue(value);
    setIsInputFocused(false);
    if (onBlur) {
      onBlur(event);
    }
  };
  var handleFocus = function handleFocus() {
    if (isManualInput && !isInputFocused) {
      var _inputRef$current;
      (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.select();
    }
    setIsInputFocused(true);
  };
  var handleKeyDown = function handleKeyDown(event) {
    if (disabled) {
      return;
    }
    if (event.keyCode === keyCodes.Up && onIncrementKey) {
      event.preventDefault();
      onIncrementKey();
      return;
    }
    if (event.keyCode === keyCodes.Down && onDecrementKey) {
      event.preventDefault();
      onDecrementKey();
      return;
    }
    if (event.keyCode === keyCodes.Enter) {
      event.preventDefault();
      validateValue(value);
      if (onKeyDown) {
        onKeyDown(event);
      }
    }
  };
  var handleEndErrorAnimation = function handleEndErrorAnimation(correctValue) {
    setIsAnimationRun(false);
    setIsInputFocused(false);
    setErrorClass(undefined);
    setValues(null, correctValue);
  };
  useEffect(function () {
    setDynamicWidth(getInputWidth());
  }, []);
  useDidMountEffect(function () {
    setDynamicWidth(getInputWidth(false));
  }, [value]);
  useEffect(function () {
    if (shouldFocusInput && inputRef.current) {
      inputRef.current.focus();
      onFocusHandled === null || onFocusHandled === void 0 || onFocusHandled();
    }
  }, [shouldFocusInput]);
  return /*#__PURE__*/React__default.createElement(InputWrapper, {
    ref: wrapperRef,
    className: cx(solidViewClass, errorClass, manualInputClass),
    isManualInput: Boolean(isManualInput),
    onClick: handleClickInputWrapper
  }, /*#__PURE__*/React__default.createElement(TextWrapper, {
    ref: textWrapperRef
  }, !isLoading && textBefore && /*#__PURE__*/React__default.createElement(AdditionalText, {
    className: classes.textBefore
  }, textBefore), isLoading ? /*#__PURE__*/React__default.createElement(Loader, null, loader || _StyledSpinner || (_StyledSpinner = /*#__PURE__*/React__default.createElement(StyledSpinner, null))) : /*#__PURE__*/React__default.createElement(DynamicInput, null, /*#__PURE__*/React__default.createElement(Input, _extends({
    ref: inputForkRef,
    dynamicWidth: dynamicWidth,
    value: value,
    isManualInput: Boolean(isManualInput),
    tabIndex: disabled ? -1 : 0,
    onChange: handleManualInputChange,
    onFocus: handleFocus,
    onBlur: handleBlur,
    onKeyDown: handleKeyDown,
    onAnimationEnd: function onAnimationEnd() {
      return handleEndErrorAnimation(Number(errorValue));
    }
  }, rest)), /*#__PURE__*/React__default.createElement(InputWidthHelper, {
    ref: inputHelperRef
  }, value)), !isLoading && textAfter && /*#__PURE__*/React__default.createElement(AdditionalText, {
    className: classes.textAfter
  }, textAfter)));
});

export { NumberInput };
