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; };

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; }

import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import numbro from 'numbro';
import languages from 'numbro/dist/languages.min';
import is from 'is';

import Input from '../Input';
import { countDecimals } from '../Input/utility';
import Error from '../Input/error';
import { InputContext } from '../Input/context';
import { validNumber } from '../Input/validate';
import './style.css';

var Currency = function Currency(props) {
  var ref = React.createRef();
  return React.createElement(
    InputContext.Consumer,
    null,
    function (context) {
      var upRef = React.createRef();
      var downRef = React.createRef();
      var inputClasses = classNames({
        'ma__input-currency__control': true,
        'js-is-required': props.required,
        'ma__input-currency__control--showButtons': props.showButtons
      });
      var toCurrency = function toCurrency(number, decimal) {
        if (is.number(number)) {
          if (props.language) {
            var i = 0;
            var langKeys = Object.keys(languages);
            var langMax = langKeys.length;
            for (; i < langMax; i += 1) {
              var langKey = langKeys[i];
              var lang = languages[langKey];
              numbro.registerLanguage(lang);
            }
            numbro.setLanguage(props.language);
          }
          var currency = numbro(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) && is.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 && !is.number(val)) {
          var errorMsg = 'Please enter a value.';
          return {
            showError: true,
            errorMsg: errorMsg
          };
        } else if (is.number(val)) {
          var _validNumber = 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(numbro.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(!is.empty(stringValue) ? numberValue : '');
        context.updateState(_extends({ value: stringValue }, updateError), function () {
          if (is.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(numbro.unformat(stringValue)) : 0;
        var newValue = void 0;
        if (direction === 'up') {
          newValue = Number(numbro(numberValue).add(props.step).format({ mantissa: countDecimals(props.step) }));
        } else if (direction === 'down') {
          newValue = Number(numbro(numberValue).subtract(props.step).format({ mantissa: countDecimals(props.step) }));
        }
        if (greaterThanMin(newValue) && lessThanMax(newValue)) {
          var updateError = displayErrorMessage(!is.empty(stringValue) ? newValue : '');
          context.updateState(_extends({ value: toCurrency(newValue, countDecimals(props.step)) }, updateError), function () {
            if (is.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(numbro.unformat(stringValue)) : 0;
        // default to 0 if defaultValue is NaN
        if (is.number(numberValue) && !is.empty(stringValue)) {
          var newValue = numberValue;
          if (key === 'ArrowDown') {
            newValue = Number(numbro(numberValue).subtract(props.step).format({ mantissa: countDecimals(props.step) }));
            if (greaterThanMin(newValue) && lessThanMax(newValue)) {
              var updateError = displayErrorMessage(!is.empty(stringValue) ? newValue : '');
              context.updateState(_extends({ value: toCurrency(newValue, countDecimals(props.step)) }, updateError), function () {
                if (is.fn(props.onChange)) {
                  props.onChange(newValue, props.id, type, key);
                }
              });
            }
          } else if (key === 'ArrowUp') {
            newValue = Number(numbro(numberValue).add(props.step).format({ mantissa: countDecimals(props.step) }));
            if (greaterThanMin(newValue) && lessThanMax(newValue)) {
              var _updateError = displayErrorMessage(!is.empty(stringValue) ? newValue : '');
              context.updateState(_extends({ value: toCurrency(newValue, countDecimals(props.step)) }, _updateError), function () {
                if (is.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(numbro.unformat(stringValue)));
        if (isNotNumber) {
          inputEl.setAttribute('placeholder', props.placeholder);
        }
        var newValue = isNotNumber ? '' : Number(numbro.unformat(stringValue));
        if (!is.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, countDecimals(props.step)) }, updateError), function () {
            if (is.fn(props.onBlur)) {
              props.onBlur(newValue, { id: props.id, type: type });
            }
          });
        }
      };

      var handleFocus = function handleFocus() {
        var inputEl = ref.current;
        if (is.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: is.number(props.maxlength) ? Number(props.maxlength) : null,
        style: !is.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 React.createElement(
        'div',
        { className: 'ma__input-currency' },
        React.createElement('input', inputAttr),
        props.showButtons && React.createElement(
          'div',
          { className: 'ma__input-number__control-buttons' },
          React.createElement('button', {
            type: 'button',
            'aria-label': 'increase value',
            className: 'ma__input-currency__control-plus',
            onClick: handleAdjust,
            disabled: props.disabled,
            tabIndex: -1,
            ref: upRef
          }),
          React.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: PropTypes.bool,
  showButtons: PropTypes.bool,
  language: PropTypes.string,
  /* eslint-disable-next-line react/forbid-prop-types */
  format: PropTypes.object,
  max: PropTypes.number,
  min: PropTypes.number,
  onChange: PropTypes.func,
  onBlur: PropTypes.func,
  step: PropTypes.number,
  placeholder: PropTypes.string,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  maxlength: PropTypes.number,
  width: PropTypes.number,
  disabled: PropTypes.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 (!is.empty(inputProps.defaultValue)) {
    var currency = numbro(inputProps.defaultValue);
    inputProps.defaultValue = currency.formatCurrency(format);
  }
  return React.createElement(
    Input,
    inputProps,
    React.createElement(Currency, currencyProps),
    React.createElement(Error, { id: props.id })
  );
};

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

export default InputCurrency;