'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.LoanSimulator = undefined;

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 _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

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 _number = require('kitten/helpers/utils/number');

var _sliderWithTooltipAndPower = require('kitten/components/sliders/slider-with-tooltip-and-power');

var _textInputWithUnit = require('kitten/components/form/text-input-with-unit');

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

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // Simulator that lets users select an amount and an installment, to start
// simulating a loan.

var LoanSimulator = exports.LoanSimulator = function (_React$Component) {
  _inherits(LoanSimulator, _React$Component);

  function LoanSimulator(props) {
    _classCallCheck(this, LoanSimulator);

    var _this = _possibleConstructorReturn(this, (LoanSimulator.__proto__ || Object.getPrototypeOf(LoanSimulator)).call(this, props));

    _this.state = {
      amount: props.initialAmount * 1,
      installmentAmount: props.initialInstallment,
      dragged: !!props.initialInstallment,
      touched: props.initialTouched
    };

    _this.handleFocus = _this.handleFocus.bind(_this);
    _this.handleAmountChange = _this.handleAmountChange.bind(_this);
    _this.handleEnter = _this.handleEnter.bind(_this);
    _this.handleInstallmentLabelClick = _this.handleInstallmentLabelClick.bind(_this);
    _this.handleInstallmentChange = _this.handleInstallmentChange.bind(_this);
    _this.handleInstallmentAction = _this.handleInstallmentAction.bind(_this);
    return _this;
  }

  _createClass(LoanSimulator, [{
    key: 'handleFocus',
    value: function handleFocus(e) {
      this.setState({
        touched: false,
        installmentAmount: null
      });
    }
  }, {
    key: 'handleAmountChange',
    value: function handleAmountChange(e) {
      this.setState({ amount: e.target.value });
    }
  }, {
    key: 'handleEnter',
    value: function handleEnter(e) {
      this.setState({ touched: true });
    }
  }, {
    key: 'handleInstallmentLabelClick',
    value: function handleInstallmentLabelClick() {
      this.refs.content.focusSlider();
    }

    // on slider click or on grab change

  }, {
    key: 'handleInstallmentChange',
    value: function handleInstallmentChange(value) {
      this.setState({
        installmentAmount: value,
        dragged: true
      });
    }
  }, {
    key: 'handleInstallmentAction',
    value: function handleInstallmentAction() {
      this.setState({ touched: true });
    }
  }, {
    key: 'duration',
    value: function duration() {
      if (this.state.installmentAmount) return Math.ceil(this.state.amount / this.state.installmentAmount);
    }
  }, {
    key: 'commissionRate',
    value: function commissionRate() {
      var duration = this.duration();
      for (var i = 0, len = this.props.commissionRules.length; i < len; i++) {
        var rule = this.props.commissionRules[i];
        if (!rule.durationMax || duration <= rule.durationMax) return rule.rate;
      }
    }
  }, {
    key: 'commissionAmount',
    value: function commissionAmount() {
      return this.commissionRate() * this.state.amount;
    }
  }, {
    key: 'installmentMin',
    value: function installmentMin() {
      var installmentStep = this.installmentStep();
      var value = this.state.amount / this.props.durationMax;
      var min = Math.ceil(value / installmentStep) * installmentStep;

      if (min > this.state.amount * 1) return this.state.amount;else return min;
    }
  }, {
    key: 'installmentMax',
    value: function installmentMax() {
      return this.state.amount * 1;
    }
  }, {
    key: 'installmentStep',
    value: function installmentStep() {
      if (this.state.installmentAmount > 1000) return 100;
      if (this.state.installmentAmount > 200) return 10;
      return 1;
    }
  }, {
    key: 'error',
    value: function error() {
      if (!this.state.touched) return null;

      return this.amountError();
    }
  }, {
    key: 'amountError',
    value: function amountError() {
      if (!this.state.amount) return this.props.amountEmptyError;

      if (!_number.numberUtils.isNumber(this.state.amount) || this.state.amount < this.props.amountMin || this.state.amount > this.props.amountMax) return this.props.amountOutOfBoundsError;
    }
  }, {
    key: 'render',
    value: function render() {
      return _react2.default.createElement(LoanSimulatorContent, _extends({
        ref: 'content'
      }, this.props, this.state, {
        onFocus: this.handleFocus,
        onAmountChange: this.handleAmountChange,
        onEnter: this.handleEnter,
        onInstallmentLabelClick: this.handleInstallmentLabelClick,
        onInstallmentChange: this.handleInstallmentChange,
        onInstallmentAction: this.handleInstallmentAction,
        duration: this.duration(),
        commissionAmount: this.commissionAmount(),
        commissionRate: this.commissionRate(),
        installmentMin: this.installmentMin(),
        installmentMax: this.installmentMax(),
        installmentStep: this.installmentStep(),
        error: this.error(),
        amountError: this.amountError()
      }));
    }
  }]);

  return LoanSimulator;
}(_react2.default.Component);

var LoanSimulatorContent = function (_React$Component2) {
  _inherits(LoanSimulatorContent, _React$Component2);

  function LoanSimulatorContent(props) {
    _classCallCheck(this, LoanSimulatorContent);

    var _this2 = _possibleConstructorReturn(this, (LoanSimulatorContent.__proto__ || Object.getPrototypeOf(LoanSimulatorContent)).call(this, props));

    _this2.handleAmountKeyDown = _this2.handleAmountKeyDown.bind(_this2);
    _this2.handleInstallmentChange = _this2.handleInstallmentChange.bind(_this2);
    return _this2;
  }

  // Allow parents to focus the slider


  _createClass(LoanSimulatorContent, [{
    key: 'focusSlider',
    value: function focusSlider() {
      this.slider.focus();
    }
  }, {
    key: 'handleAmountKeyDown',
    value: function handleAmountKeyDown(e) {
      // when pressing enter
      if (e.keyCode == 13) {
        this.focusSlider();
        this.props.onEnter();
      }
    }
  }, {
    key: 'handleInstallmentChange',
    value: function handleInstallmentChange(value, ratio) {
      this.amount.blur();
      this.props.onInstallmentChange(value, ratio);
    }
  }, {
    key: 'toCurrency',
    value: function toCurrency(cents) {
      if (isNaN(cents)) return null;

      return (cents / 100).toLocaleString(this.props.locale);
    }
  }, {
    key: 'sliderIsActive',
    value: function sliderIsActive() {
      return !this.props.amountError && this.props.dragged && this.props.installmentAmount;
    }
  }, {
    key: 'renderCommission',
    value: function renderCommission() {
      if (!this.props.displayCommission) return;

      var active = this.sliderIsActive();
      var amount = active ? this.toCurrency(this.props.commissionAmount * 100) : '--';

      var commissionAmount = ' 0 ';
      var exemptionText = null;

      if (!this.props.feesExemption) {
        commissionAmount = ' ' + amount + ' ';
      } else {
        var text = '\n        (' + this.props.feesExemptionLabel + '\n        ' + amount + '\n        ' + this.props.currencySymbol + ')\n      ';

        exemptionText = _react2.default.createElement(
          'span',
          { className: 'k-LoanSimulator__feesExemption' },
          text
        );
      }

      commissionAmount += ' ' + this.props.currencySymbol;

      return _react2.default.createElement(
        'div',
        { className: 'k-LoanSimulator__commission' },
        this.props.commissionLabel,
        _react2.default.createElement(
          'span',
          {
            className: (0, _classnames2.default)({
              'k-u-text--active': active,
              'k-u-text--inactive': !active
            })
          },
          commissionAmount
        ),
        exemptionText
      );
    }
  }, {
    key: 'renderDurationError',
    value: function renderDurationError() {
      var _props = this.props,
          duration = _props.duration,
          touched = _props.touched,
          requiredDurationError = _props.requiredDurationError;


      if (!touched || duration > 0 || !requiredDurationError) return;

      return _react2.default.createElement(
        'span',
        { className: 'k-LoanSimulator__durationError' },
        this.props.requiredDurationError
      );
    }
  }, {
    key: 'renderButton',
    value: function renderButton() {
      if (!this.props.actionLabel) return;

      return _react2.default.createElement(
        'div',
        { className: 'k-LoanSimulator__actions' },
        _react2.default.createElement(
          'button',
          { className: 'k-Button k-Button--helium k-Button--big' },
          this.props.actionLabel
        )
      );
    }
  }, {
    key: 'render',
    value: function render() {
      var _this3 = this;

      var _props2 = this.props,
          label = _props2.label,
          dragged = _props2.dragged,
          touched = _props2.touched,
          duration = _props2.duration,
          error = _props2.error;

      var amountValid = !this.props.amountError;
      var showResult = !error && touched && duration;
      var installmentMin = amountValid ? this.props.installmentMin : 0;
      var installmentMax = amountValid ? this.props.installmentMax : 0;
      var installmentAmount = amountValid ? this.props.installmentAmount : 0;
      var installmentPercentage = amountValid ? this.props.installmentPercentage : 0;

      var errorClass = void 0,
          errorTag = void 0,
          tooltipClass = void 0,
          tooltipText = void 0;

      if (error) {
        errorClass = 'is-error';
        errorTag = _react2.default.createElement(
          'p',
          { className: 'k-LoanSimulator__amount__error' },
          error
        );
      }

      if (this.sliderIsActive()) {
        var durationSymbol = duration === 1 ? this.props.durationSymbol : this.props.durationSymbolPlural;

        var installmentText = '\n        ' + this.toCurrency(installmentAmount * 100) + '\n        ' + this.props.installmentSymbol + '\n      ';
        var durationText = '\n        ' + this.props.durationText + '\n        ' + duration + '\n        ' + durationSymbol + '\n      ';

        tooltipClass = null;
        tooltipText = [_react2.default.createElement(
          'div',
          { key: '1', className: 'k-LoanSimulator__installment' },
          installmentText
        ), _react2.default.createElement(
          'div',
          { key: '2', className: 'k-LoanSimulator__duration' },
          durationText
        )];
      } else {
        tooltipClass = 'is-inactive';
        tooltipText = this.props.sliderPlaceholder;
      }

      var durationInput = void 0;
      if (this.props.durationName) durationInput = _react2.default.createElement('input', {
        type: 'hidden',
        name: this.props.durationName,
        value: this.props.duration || ''
      });

      return _react2.default.createElement(
        'div',
        { className: (0, _classnames2.default)('k-LoanSimulator', errorClass) },
        _react2.default.createElement(
          'div',
          { className: 'k-LoanSimulator__amount' },
          _react2.default.createElement(
            'label',
            {
              className: 'k-Label k-LoanSimulator__label',
              htmlFor: 'loan-simulator-amount'
            },
            this.props.amountLabel
          ),
          _react2.default.createElement(_textInputWithUnit.TextInputWithUnit, {
            ref: function ref(input) {
              return _this3.amount = input;
            },
            error: error,
            id: 'loan-simulator-amount',
            name: this.props.amountName,
            type: 'number',
            min: this.props.amountMin,
            max: this.props.amountMax,
            defaultValue: this.props.initialAmount,
            onFocus: this.props.onFocus,
            onChange: this.props.onAmountChange,
            onKeyDown: this.props.onAmountKeyDown,
            placeholder: this.props.amountPlaceholder,
            unit: this.props.currencySymbol
          }),
          errorTag
        ),
        _react2.default.createElement(
          'div',
          null,
          _react2.default.createElement(
            'label',
            {
              className: 'k-Label k-LoanSimulator__label',
              onClick: this.props.onInstallmentLabelClick
            },
            this.props.installmentLabel
          ),
          _react2.default.createElement(_sliderWithTooltipAndPower.SliderWithTooltipAndPower, {
            ref: function ref(input) {
              return _this3.slider = input;
            },
            step: this.props.installmentStep,
            min: installmentMin,
            max: installmentMax,
            power: 2,
            name: this.props.installmentName,
            value: installmentAmount,
            onChange: this.handleInstallmentChange,
            onAction: this.props.onInstallmentAction,
            tooltipClass: tooltipClass,
            tooltipText: tooltipText
          }),
          this.renderCommission(),
          durationInput,
          this.renderDurationError()
        ),
        this.renderButton()
      );
    }
  }]);

  return LoanSimulatorContent;
}(_react2.default.Component);

LoanSimulator.propTypes = {
  // Label for amount input
  amountLabel: _propTypes2.default.string,

  // Name attribute for the amount input (if needed)
  amountName: _propTypes2.default.string,

  // Name attribute for the hidden installment input (if needed)
  installmentName: _propTypes2.default.string,

  // Name attribute for the hidden duration input (if needed)
  durationName: _propTypes2.default.string,

  // Placeholder for amount input
  amountPlaceholder: _propTypes2.default.string,

  // Bounds for accepted amount
  amountMin: _propTypes2.default.number,
  amountMax: _propTypes2.default.number,

  // Default amount
  initialAmount: _propTypes2.default.number,

  // Set this to true to show errors on first use
  initialTouched: _propTypes2.default.bool,

  // Error text when the amount is empty or non-numerical
  amountEmptyError: _propTypes2.default.string,

  // Error text when the amount is over or under the min and max
  amountOutOfBoundsError: _propTypes2.default.string,

  // Error text when the duration has not been set
  requiredDurationError: _propTypes2.default.string,

  // Display commission if requested
  displayCommission: _propTypes2.default.bool,
  commissionLabel: _propTypes2.default.string,
  commissionRules: _propTypes2.default.array,

  // Label before the slider
  installmentLabel: _propTypes2.default.string,

  // Text before the computed duration
  durationText: _propTypes2.default.string,

  // Bounds for the computed duration
  durationMin: _propTypes2.default.number,
  durationMax: _propTypes2.default.number,

  // Duration value (months)
  durationSymbol: _propTypes2.default.string,
  durationSymbolPlural: _propTypes2.default.string,

  // Currency
  currencySymbol: _propTypes2.default.string,

  // Installment
  installmentSymbol: _propTypes2.default.string,

  // Locale to format amounts correctly
  locale: _propTypes2.default.string,

  // Submit button
  actionLabel: _propTypes2.default.string
};

LoanSimulator.defaultProps = {
  amountLabel: 'I need',
  amountPlaceholder: '',
  amountMin: 1,
  amountMax: 10000,

  initialAmount: null,
  initialTouched: false,

  amountEmptyError: 'Amount cannot be empty',
  amountOutOfBoundsError: 'Amount is either too big or too small',
  requiredDurationError: 'Duration is required',

  displayCommission: false,
  feesExemption: false,
  feesExemptionLabel: 'instead of',
  commissionLabel: 'Fees:',

  // The `commissionRules` prop has to be an array containing a `durationMax`
  // rule. This will return the first `rate` which matches the rule for the
  // current `duration`.
  //
  // Example `commissionRules` prop:
  //     [
  //       { durationMax: 12, rate: 0.3 },
  //       { durationMax: 20, rate: 0.2 },
  //       { rate: 0.1 }
  //     ]
  commissionRules: [],

  installmentLabel: "I'd like to reimburse",
  initialInstallment: null,

  durationText: 'during',
  durationMin: 1,
  durationMax: 36,
  durationSymbol: 'month',
  durationSymbolPlural: 'months',

  currencySymbol: '$',
  installmentSymbol: '$/month',
  locale: 'en',

  actionLabel: null

  // DEPRECATED: do not use default export.
};exports.default = LoanSimulator;