'use strict';

exports.__esModule = true;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _numbro = require('numbro');

var _numbro2 = _interopRequireDefault(_numbro);

var _languages = require('numbro/dist/languages.min');

var _languages2 = _interopRequireDefault(_languages);

var _is = require('is');

var _is2 = _interopRequireDefault(_is);

var _Input = require('../Input');

var _Input2 = _interopRequireDefault(_Input);

var _utility = require('../Input/utility');

var _error = require('../Input/error');

var _error2 = _interopRequireDefault(_error);

var _context = require('../Input/context');

var _validate = require('../Input/validate');

require('./style.css');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

var Currency = function Currency(props) {
  var ref = _react2.default.createRef();
  return _react2.default.createElement(
    _context.InputContext.Consumer,
    null,
    function (context) {
      var upRef = _react2.default.createRef();
      var downRef = _react2.default.createRef();
      var inputClasses = (0, _classnames2.default)({
        'ma__input-currency__control': true,
        'js-is-required': props.required,
        'ma__input-currency__control--showButtons': props.showButtons
      });
      var toCurrency = function toCurrency(number, decimal) {
        if (_is2.default.number(number)) {
          if (props.language) {
            var i = 0;
            var langKeys = Object.keys(_languages2.default);
            var langMax = langKeys.length;
            for (; i < langMax; i += 1) {
              var langKey = langKeys[i];
              var lang = _languages2.default[langKey];
              _numbro2.default.registerLanguage(lang);
            }
            _numbro2.default.setLanguage(props.language);
          }
          var currency = (0, _numbro2.default)(number);
          var format = props.format;

          if (decimal) {
            format.mantissa = decimal;
          }
          return currency.formatCurrency(format);
        }
        return number;
      };
      var hasNumberProperty = function hasNumberProperty(obj, property) {
        return Object.prototype.hasOwnProperty.call(obj, property) && _is2.default.number(obj[property]);
      };
      var greaterThanMin = function greaterThanMin(val) {
        return !hasNumberProperty(props, 'min') || val >= props.min;
      };
      var lessThanMax = function lessThanMax(val) {
        return !hasNumberProperty(props, 'max') || val <= props.max;
      };

      var displayErrorMessage = function displayErrorMessage(val) {
        var min = props.min,
            max = props.max,
            required = props.required;

        if (required && !_is2.default.number(val)) {
          var errorMsg = 'Please enter a value.';
          return {
            showError: true,
            errorMsg: errorMsg
          };
        } else if (_is2.default.number(val)) {
          var _validNumber = (0, _validate.validNumber)(val, min, max),
              showError = _validNumber.showError,
              _errorMsg = _validNumber.errorMsg;

          return {
            showError: showError, errorMsg: _errorMsg
          };
        }
        return {
          showError: false,
          errorMsg: ''
        };
      };

      var handleChange = function handleChange(e) {
        var type = e.type;

        var stringValue = ref.current.value;
        var numberValue = stringValue ? Number(_numbro2.default.unformat(stringValue)) : 0;
        // If the stringvalue is empty, set to empty string so the required error
        // message is rendered. Otherwise pass the number value for the min/max check.
        var updateError = displayErrorMessage(!_is2.default.empty(stringValue) ? numberValue : '');
        context.updateState(_extends({ value: stringValue }, updateError), function () {
          if (_is2.default.fn(props.onChange)) {
            props.onChange(numberValue, props.id, type);
          }
        });
      };

      var handleAdjust = function handleAdjust(e) {
        var direction = e.currentTarget === upRef.current ? 'up' : 'down';
        var type = e.type;

        var stringValue = ref.current.value;
        var numberValue = stringValue ? Number(_numbro2.default.unformat(stringValue)) : 0;
        var newValue = void 0;
        if (direction === 'up') {
          newValue = Number((0, _numbro2.default)(numberValue).add(props.step).format({ mantissa: (0, _utility.countDecimals)(props.step) }));
        } else if (direction === 'down') {
          newValue = Number((0, _numbro2.default)(numberValue).subtract(props.step).format({ mantissa: (0, _utility.countDecimals)(props.step) }));
        }
        if (greaterThanMin(newValue) && lessThanMax(newValue)) {
          var updateError = displayErrorMessage(!_is2.default.empty(stringValue) ? newValue : '');
          context.updateState(_extends({ value: toCurrency(newValue, (0, _utility.countDecimals)(props.step)) }, updateError), function () {
            if (_is2.default.fn(props.onChange)) {
              props.onChange(newValue, props.id, type, direction);
            }
          });
        }
      };

      var handleKeyDown = function handleKeyDown(e) {
        var type = e.type,
            key = e.key;

        var stringValue = ref.current.value;
        var numberValue = stringValue ? Number(_numbro2.default.unformat(stringValue)) : 0;
        // default to 0 if defaultValue is NaN
        if (_is2.default.number(numberValue) && !_is2.default.empty(stringValue)) {
          var newValue = numberValue;
          if (key === 'ArrowDown') {
            newValue = Number((0, _numbro2.default)(numberValue).subtract(props.step).format({ mantissa: (0, _utility.countDecimals)(props.step) }));
            if (greaterThanMin(newValue) && lessThanMax(newValue)) {
              var updateError = displayErrorMessage(!_is2.default.empty(stringValue) ? newValue : '');
              context.updateState(_extends({ value: toCurrency(newValue, (0, _utility.countDecimals)(props.step)) }, updateError), function () {
                if (_is2.default.fn(props.onChange)) {
                  props.onChange(newValue, props.id, type, key);
                }
              });
            }
          } else if (key === 'ArrowUp') {
            newValue = Number((0, _numbro2.default)(numberValue).add(props.step).format({ mantissa: (0, _utility.countDecimals)(props.step) }));
            if (greaterThanMin(newValue) && lessThanMax(newValue)) {
              var _updateError = displayErrorMessage(!_is2.default.empty(stringValue) ? newValue : '');
              context.updateState(_extends({ value: toCurrency(newValue, (0, _utility.countDecimals)(props.step)) }, _updateError), function () {
                if (_is2.default.fn(props.onChange)) {
                  props.onChange(newValue, props.id, type, key);
                }
              });
            }
          }
        }
      };

      var handleBlur = function handleBlur(e) {
        var type = e.type;

        var inputEl = ref.current;
        var stringValue = inputEl.value;
        // isNotNumber returns true if stringValue is null, undefined or 'NaN'
        /* eslint-disable-next-line   no-restricted-globals */
        var isNotNumber = !stringValue || isNaN(Number(_numbro2.default.unformat(stringValue)));
        if (isNotNumber) {
          inputEl.setAttribute('placeholder', props.placeholder);
        }
        var newValue = isNotNumber ? '' : Number(_numbro2.default.unformat(stringValue));
        if (!_is2.default.empty(newValue)) {
          if (hasNumberProperty(props, 'max') && newValue > props.max) {
            newValue = props.max;
          }
          if (hasNumberProperty(props, 'min') && newValue < props.min) {
            newValue = props.min;
          }
          var updateError = displayErrorMessage(newValue);
          context.updateState(_extends({ value: toCurrency(newValue, (0, _utility.countDecimals)(props.step)) }, updateError), function () {
            if (_is2.default.fn(props.onBlur)) {
              props.onBlur(newValue, { id: props.id, type: type });
            }
          });
        }
      };

      var handleFocus = function handleFocus() {
        var inputEl = ref.current;
        if (_is2.default.empty(inputEl.value)) {
          inputEl.removeAttribute('placeholder');
        }
      };

      var inputAttr = {
        className: inputClasses,
        name: props.name,
        id: props.id,
        type: 'text',
        placeholder: props.placeholder,
        'data-type': 'text',
        maxLength: _is2.default.number(props.maxlength) ? Number(props.maxlength) : null,
        style: !_is2.default.empty(props.width) ? { width: props.width + 'px' } : null,
        ref: ref,
        onChange: handleChange,
        onBlur: handleBlur,
        onFocus: handleFocus,
        onKeyDown: handleKeyDown,
        required: props.required,
        value: context.getValue(),
        disabled: props.disabled
      };

      return _react2.default.createElement(
        'div',
        { className: 'ma__input-currency' },
        _react2.default.createElement('input', inputAttr),
        props.showButtons && _react2.default.createElement(
          'div',
          { className: 'ma__input-number__control-buttons' },
          _react2.default.createElement('button', {
            type: 'button',
            'aria-label': 'increase value',
            className: 'ma__input-currency__control-plus',
            onClick: handleAdjust,
            disabled: props.disabled,
            tabIndex: -1,
            ref: upRef
          }),
          _react2.default.createElement('button', {
            type: 'button',
            'aria-label': 'decrease value',
            className: 'ma__input-currency__control-minus',
            onClick: handleAdjust,
            disabled: props.disabled,
            tabIndex: -1,
            ref: downRef
          })
        )
      );
    }
  );
};

Currency.propTypes = process.env.NODE_ENV !== "production" ? {
  required: _propTypes2.default.bool,
  showButtons: _propTypes2.default.bool,
  language: _propTypes2.default.string,
  /* eslint-disable-next-line react/forbid-prop-types */
  format: _propTypes2.default.object,
  max: _propTypes2.default.number,
  min: _propTypes2.default.number,
  onChange: _propTypes2.default.func,
  onBlur: _propTypes2.default.func,
  step: _propTypes2.default.number,
  placeholder: _propTypes2.default.string,
  id: _propTypes2.default.string.isRequired,
  name: _propTypes2.default.string.isRequired,
  maxlength: _propTypes2.default.number,
  width: _propTypes2.default.number,
  disabled: _propTypes2.default.bool
} : {};

var InputCurrency = function InputCurrency(props) {
  var max = props.max,
      min = props.min,
      step = props.step,
      name = props.name,
      onChange = props.onChange,
      onBlur = props.onBlur,
      placeholder = props.placeholder,
      width = props.width,
      maxlength = props.maxlength,
      format = props.format,
      language = props.language,
      showButtons = props.showButtons,
      inputProps = _objectWithoutProperties(props, ['max', 'min', 'step', 'name', 'onChange', 'onBlur', 'placeholder', 'width', 'maxlength', 'format', 'language', 'showButtons']);
  // Input and Currency share the props.required and props.id values.


  var currencyProps = {
    max: max,
    min: min,
    step: step,
    name: name,
    placeholder: placeholder,
    width: width,
    maxlength: maxlength,
    required: props.required,
    id: props.id,
    onChange: onChange,
    onBlur: onBlur,
    format: format,
    language: language,
    disabled: props.disabled,
    showButtons: showButtons
  };
  if (!_is2.default.empty(inputProps.defaultValue)) {
    var currency = (0, _numbro2.default)(inputProps.defaultValue);
    inputProps.defaultValue = currency.formatCurrency(format);
  }
  return _react2.default.createElement(
    _Input2.default,
    inputProps,
    _react2.default.createElement(Currency, currencyProps),
    _react2.default.createElement(_error2.default, { id: props.id })
  );
};

InputCurrency.propTypes = process.env.NODE_ENV !== "production" ? {
  /** Whether the label should be hidden or not */
  hiddenLabel: _propTypes2.default.bool,
  /** The label text for the input field, can be a string or a component */
  labelText: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]).isRequired,
  /** Whether the field is required or not */
  required: _propTypes2.default.bool,
  /** Whether the field is disabled or not */
  disabled: _propTypes2.default.bool,
  /** The unique ID for the input field */
  id: _propTypes2.default.string.isRequired,
  /** The name for the input field */
  name: _propTypes2.default.string.isRequired,
  /** The max acceptable input length */
  maxlength: _propTypes2.default.number,
  /** The pattern to filter input against, e.g. "[0-9]" for numbers only */
  pattern: _propTypes2.default.string,
  /** The number of characters wide to make the input field */
  width: _propTypes2.default.number,
  /** The placeholder text for the input field */
  placeholder: _propTypes2.default.string,
  /** The message to be displayed in the event of an error. */
  errorMsg: _propTypes2.default.string,
  /** Custom change function */
  onChange: _propTypes2.default.func,
  /** Custom onBlur function */
  onBlur: _propTypes2.default.func,
  /** Default input value */
  defaultValue: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
  /** Max value for the field. */
  max: _propTypes2.default.number,
  /** Min value for the field. */
  min: _propTypes2.default.number,
  /** Using the up/down arrow keys will increment/decrement the input value by this number. */
  step: _propTypes2.default.number,
  /** A language tag that represents what country the currency should display. Comes from IETF BCP 47: https://numbrojs.com/languages.html */
  language: _propTypes2.default.string,
  /** Numbro Formatting options for displaying the currency. See https://numbrojs.com/format.html */
  /* eslint-disable-next-line react/forbid-prop-types */
  format: _propTypes2.default.object,
  /** Inline label and input field */
  inline: _propTypes2.default.bool,
  /** Whether to render up/down buttons */
  showButtons: _propTypes2.default.bool
} : {};
InputCurrency.defaultProps = {
  hiddenLabel: false,
  required: false,
  onChange: null,
  onBlur: null,
  language: 'en-US',
  format: {
    mantissa: 2,
    trimMantissa: false,
    thousandSeparated: true,
    negative: 'parenthesis'
  },
  step: 0.01,
  showButtons: true
};

exports.default = InputCurrency;
module.exports = exports['default'];