import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _typeof from "@babel/runtime/helpers/typeof";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _extends from "@babel/runtime/helpers/extends";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _inherits from "@babel/runtime/helpers/inherits";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
var _excluded = ["value"];

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

import React, { PureComponent, forwardRef } from 'react';
import PropTypes from 'prop-types';
import { IconAddSmallOutline, IconChevronUpSmallOutline, IconChevronDownSmallOutline, IconMinusSmallOutline } from '@teamleader/ui-icons';
import Button from '../button';
import Icon from '../icon';
import SingleLineInputBase from './SingleLineInputBase';
import omit from 'lodash.omit';
import theme from './theme.css';
import { parseValue, toNumber } from './utils';
import { KEY } from '../../constants';

var StepperControls = /*#__PURE__*/function (_PureComponent) {
  _inherits(StepperControls, _PureComponent);

  var _super = _createSuper(StepperControls);

  function StepperControls() {
    _classCallCheck(this, StepperControls);

    return _super.apply(this, arguments);
  }

  _createClass(StepperControls, [{
    key: "render",
    value: function render() {
      var _this$props = this.props,
          inverse = _this$props.inverse,
          stepperUpProps = _this$props.stepperUpProps,
          stepperDownProps = _this$props.stepperDownProps;
      var iconProps = {
        color: inverse ? 'teal' : 'neutral',
        element: 'button',
        tabIndex: '-1',
        tint: inverse ? 'lightest' : 'darkest',
        type: 'button'
      };
      return /*#__PURE__*/React.createElement("div", {
        className: theme['stepper']
      }, /*#__PURE__*/React.createElement(Icon, _extends({
        className: theme['stepper-up']
      }, stepperUpProps, iconProps), /*#__PURE__*/React.createElement(IconChevronUpSmallOutline, null)), /*#__PURE__*/React.createElement(Icon, _extends({
        className: theme['stepper-down']
      }, stepperDownProps, iconProps), /*#__PURE__*/React.createElement(IconChevronDownSmallOutline, null)));
    }
  }]);

  return StepperControls;
}(PureComponent);

var NumericInput = /*#__PURE__*/function (_PureComponent2) {
  _inherits(NumericInput, _PureComponent2);

  var _super2 = _createSuper(NumericInput);

  function NumericInput(props) {
    var _this;

    _classCallCheck(this, NumericInput);

    _this = _super2.call(this, props);

    _defineProperty(_assertThisInitialized(_this), "handleOnChange", function (event) {
      var onChange = _this.props.onChange;
      onChange && onChange(event, event.currentTarget.value);
    });

    _defineProperty(_assertThisInitialized(_this), "updateStep", function (n) {
      var _this$props2 = _this.props,
          min = _this$props2.min,
          max = _this$props2.max,
          value = _this$props2.value,
          step = _this$props2.step;
      var currentValue = toNumber(value || 0);
      var stepN = step * n;
      var newValue = currentValue + stepN;

      if (newValue % step) {
        newValue = Math.ceil(currentValue / stepN) * stepN;
      }

      var newValueBoundToMinMax = parseValue(newValue, min, max);
      var inputElement = _this.inputElement.current;

      if (inputElement) {
        var prototype = Object.getPrototypeOf(inputElement);
        var prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
        prototypeValueSetter.call(inputElement, newValueBoundToMinMax);
        inputElement.dispatchEvent(new Event('change', {
          bubbles: true
        }));
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleIncreaseValue", function () {
      _this.updateStep(1);
    });

    _defineProperty(_assertThisInitialized(_this), "handleDecreaseValue", function () {
      _this.updateStep(-1);
    });

    _defineProperty(_assertThisInitialized(_this), "handleDecreaseMouseDown", function () {
      _this.handleDecreaseValue();

      var parent = _assertThisInitialized(_this);

      _this.timeout.current = setTimeout(function () {
        parent.timer.current = setInterval(function () {
          if (_this.isMinReached()) {
            _this.handleClearStepperTimer();
          } else {
            _this.handleDecreaseValue();
          }
        }, 75);
      }, 300);
    });

    _defineProperty(_assertThisInitialized(_this), "handleIncreaseMouseDown", function () {
      _this.handleIncreaseValue();

      var parent = _assertThisInitialized(_this);

      _this.timeout.current = setTimeout(function () {
        parent.timer.current = setInterval(function () {
          if (_this.isMaxReached()) {
            _this.handleClearStepperTimer();
          } else {
            _this.handleIncreaseValue();
          }
        }, 75);
      }, 300);
    });

    _defineProperty(_assertThisInitialized(_this), "handleClearStepperTimer", function () {
      clearTimeout(_this.timeout.current);
      clearInterval(_this.timer.current);
    });

    _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) {
      if (event.key === KEY.ArrowUp) {
        event.preventDefault();

        _this.handleIncreaseValue();
      } else if (event.key === KEY.ArrowDown) {
        event.preventDefault();

        _this.handleDecreaseValue();
      }

      _this.props.onKeyDown && _this.props.onKeyDown(event);
    });

    _defineProperty(_assertThisInitialized(_this), "handleBlur", function () {
      var onBlur = _this.props.onBlur;
      onBlur && onBlur.apply(void 0, arguments);
    });

    _defineProperty(_assertThisInitialized(_this), "isMaxReached", function () {
      return _this.props.value >= _this.props.max;
    });

    _defineProperty(_assertThisInitialized(_this), "isMinReached", function () {
      return _this.props.value <= _this.props.min;
    });

    _defineProperty(_assertThisInitialized(_this), "getConnectedRight", function () {
      var _this$props3 = _this.props,
          connectedRight = _this$props3.connectedRight,
          size = _this$props3.size,
          stepper = _this$props3.stepper;

      if (stepper === 'connected') {
        return /*#__PURE__*/React.createElement(Button, {
          disabled: _this.isMaxReached(),
          icon: /*#__PURE__*/React.createElement(IconAddSmallOutline, null),
          onBlur: _this.handleBlur,
          onMouseDown: _this.handleIncreaseMouseDown,
          onMouseUp: _this.handleClearStepperTimer,
          onMouseLeave: _this.handleClearStepperTimer,
          size: size
        });
      }

      return connectedRight;
    });

    _defineProperty(_assertThisInitialized(_this), "getConnectedLeft", function () {
      var _this$props4 = _this.props,
          connectedLeft = _this$props4.connectedLeft,
          size = _this$props4.size,
          stepper = _this$props4.stepper;

      if (stepper === 'connected') {
        return /*#__PURE__*/React.createElement(Button, {
          disabled: _this.isMinReached(),
          icon: /*#__PURE__*/React.createElement(IconMinusSmallOutline, null),
          onMouseDown: _this.handleDecreaseMouseDown,
          onMouseUp: _this.handleClearStepperTimer,
          onMouseLeave: _this.handleClearStepperTimer,
          onBlur: _this.handleBlur,
          size: size
        });
      }

      return connectedLeft;
    });

    _defineProperty(_assertThisInitialized(_this), "getSuffix", function () {
      var _this$props5 = _this.props,
          inverse = _this$props5.inverse,
          stepper = _this$props5.stepper,
          suffix = _this$props5.suffix;

      if (stepper === 'suffix') {
        return [].concat(_toConsumableArray(suffix), [
        /*#__PURE__*/

        /* eslint-disable-next-line react/jsx-key */
        React.createElement(StepperControls, {
          inverse: inverse,
          stepperUpProps: {
            onBlur: _this.handleBlur,
            disabled: _this.isMaxReached(),
            onMouseDown: _this.handleIncreaseMouseDown,
            onMouseUp: _this.handleClearStepperTimer,
            onMouseLeave: _this.handleClearStepperTimer
          },
          stepperDownProps: {
            onBlur: _this.handleBlur,
            disabled: _this.isMinReached(),
            onMouseDown: _this.handleDecreaseMouseDown,
            onMouseUp: _this.handleClearStepperTimer,
            onMouseLeave: _this.handleClearStepperTimer
          }
        })]);
      }

      return suffix;
    });

    _defineProperty(_assertThisInitialized(_this), "setRef", function (ref) {
      _this.inputElement.current = ref;
      var forwardedRef = _this.props.forwardedRef;

      if (typeof forwardedRef === 'function') {
        forwardedRef(ref);
      } else if (_typeof(forwardedRef) === 'object' && forwardedRef !== null) {
        forwardedRef.current = ref;
      }
    });

    _this.inputElement = /*#__PURE__*/React.createRef();
    _this.timer = /*#__PURE__*/React.createRef();
    _this.timeout = /*#__PURE__*/React.createRef();
    return _this;
  }

  _createClass(NumericInput, [{
    key: "render",
    value: function render() {
      var _this$props6 = this.props,
          value = _this$props6.value,
          rest = _objectWithoutProperties(_this$props6, _excluded);

      var restProps = omit(rest, ['suffix', 'onChange', 'onKeyDown']);
      return /*#__PURE__*/React.createElement(SingleLineInputBase, _extends({
        ref: this.setRef,
        type: "number",
        value: value,
        onChange: this.handleOnChange,
        onKeyDown: this.handleKeyDown
      }, restProps, {
        connectedLeft: this.getConnectedLeft(),
        connectedRight: this.getConnectedRight(),
        suffix: this.getSuffix()
      }));
    }
  }]);

  return NumericInput;
}(PureComponent);

NumericInput.defaultProps = {
  min: Number.MIN_SAFE_INTEGER,
  max: Number.MAX_SAFE_INTEGER,
  step: 1,
  suffix: [],
  stepper: 'suffix'
};
/** @type {React.ComponentType<any>} */

var ForwardedNumericInput = /*#__PURE__*/forwardRef(function (props, ref) {
  return /*#__PURE__*/React.createElement(NumericInput, _extends({}, props, {
    forwardedRef: ref
  }));
});
ForwardedNumericInput.displayName = 'NumericInput';
export default ForwardedNumericInput;