"use strict";
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MoneyInput = void 0;
// @ts-nocheck
/* eslint react/prop-types: 0 */
var react_1 = __importDefault(require("react"));
var bem_react_classname_1 = require("bem-react-classname");
var cn_1 = require("../cn");
var input_1 = __importDefault(require("../input/input"));
var mask_1 = __importDefault(require("../masked-input/mask"));
var masked_input_1 = require("../masked-input");
var currency_codes_1 = require("../lib/currency-codes");
var DEFAULT_FRACTION_SIZE = 2;
var DEFAULT_INTEGER_SIZE = 9;
var INTEGER_PART_SIZE = 3;
var IS_ANDROID = typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent);
/**
 * Возвращает целую и дробную часть значения в виде массива.
 * Если дробная часть не равна `undefined`, значит введена дробная часть
 * или хотя бы запятая.
 *
 * @param value Значение
 */
function getValueParts(value) {
    return value
        .replace(/[.бю]/g, ',') // Заменяем точки, `б` и `ю` на запятые.
        .replace(/[^\d,]/g, '') // Удаляем все, что не является цифрой или запятой.
        .split(',') // Разделяем по запятой.
        .slice(0, 2); // Отрезаем, если больше, чем один фрагмент после запятой.
}
/**
 * Сплитит интегер в группы по 3.
 *
 * @param str Строка интегера
 */
function splitInteger(str) {
    if (str.length <= INTEGER_PART_SIZE) {
        return [str];
    }
    var from = str.length - INTEGER_PART_SIZE;
    var to = str.length;
    return [str.slice(from, to)].concat(splitInteger(str.slice(0, from)));
}
/**
 * Компонент поля для ввода суммы. Может принимать в качестве значения либо число, либо число с сотой долей.
 */
var MoneyInput = /** @class */ (function (_super) {
    __extends(MoneyInput, _super);
    function MoneyInput() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.cn = bem_react_classname_1.createCn('money-input');
        _this.state = {
            value: '',
        };
        _this.caretFixTimeout = null;
        _this.handleProcessMaskInputEvent = function (event) {
            var currentValue = _this.getValue();
            var currentFormattedValue = _this.mask.format(_this.getValue());
            var newValue = event.target.value;
            var currentSelection = _this.root.control.input.selectionStart;
            // При удалении отрезаем запятую, если исчезла дробная часть.
            if (newValue.length < currentFormattedValue.length) {
                var fractionPart = getValueParts(newValue)[1]; // Берем значение после запятой
                // `fractionPart !== undefined` - значит запятая введена, но
                // `fractionPart.length === 0` - значит цифр после запятой нет.
                if (fractionPart !== undefined && fractionPart.length === 0) {
                    newValue = newValue.substring(0, newValue.length - 1);
                    // eslint-disable-next-line no-param-reassign
                    event.target.value = newValue;
                }
            }
            _this.updateMaskByValue(newValue);
            // При добавлении/изменении через selection последней цифры целой части каретка должна
            // оставаться перед запятой
            if (newValue.length >= currentValue.length && newValue[currentSelection] === ',') {
                window.requestAnimationFrame(function () {
                    // Фикс бага смещения каретки в браузере на андроидах Jelly Bean (c 4.1 по 4.3)
                    var offsetSection = IS_ANDROID && parseFloat(masked_input_1.getAndroidVersion()) < 4.4 ? 1 : 0;
                    var newSelectionStart = _this.root.control.input.selectionStart - 1;
                    _this.setInputSelection(newSelectionStart + offsetSection);
                });
            }
        };
        _this.handleChange = function (value) {
            // если значение начинается с нуля, то следом за ним может быть только десятичный разделитель
            _this.setState(function (state) {
                if (state.value === '0' && /^0\d+/.test(value)) {
                    return { value: state.value };
                }
                return { value: value };
            });
            if (_this.props.onChange) {
                _this.props.onChange(value, Number(value.replace(/[^\d,]/g, '').replace(/,/g, '.')));
            }
        };
        return _this;
    }
    // eslint-disable-next-line camelcase
    MoneyInput.prototype.UNSAFE_componentWillMount = function () {
        this.updateMaskByValue(this.getValue());
    };
    // eslint-disable-next-line camelcase
    MoneyInput.prototype.UNSAFE_componentWillReceiveProps = function (nextProps) {
        if (this.props.value !== nextProps.value) {
            this.updateMaskByValue(nextProps.value || '');
        }
    };
    MoneyInput.prototype.componentWillUnmount = function () {
        clearTimeout(this.caretFixTimeout);
    };
    MoneyInput.prototype.render = function () {
        var _this = this;
        return (react_1.default.createElement("div", { className: this.cn({
                currency: this.props.showCurrency,
                bold: this.props.bold,
                width: this.props.width,
            }), "data-test-id": this.props['data-test-id'] },
            react_1.default.createElement(input_1.default, __assign({}, this.props, { ref: function (root) {
                    _this.root = root;
                }, formNoValidate: true, mask: this.maskPattern, maxLength: this.getMaxLength(), value: this.getValue(), leftAddons: this.props.showCurrency ? (react_1.default.createElement("span", { className: this.cn('currency') },
                    react_1.default.createElement("span", { className: this.cn('value') }, this.getCurrencySpacer()),
                    react_1.default.createElement("span", null, currency_codes_1.getCurrencySymbol(this.props.currencyCode)))) : (this.props.leftAddons), onChange: this.handleChange, onProcessMaskInputEvent: this.handleProcessMaskInputEvent }))));
    };
    /**
     * Устанавливает фокус на поле ввода.
     */
    MoneyInput.prototype.focus = function () {
        this.root.focus();
    };
    /**
     * Убирает фокус с поля ввода.
     */
    MoneyInput.prototype.blur = function () {
        this.root.blur();
    };
    /**
     * Скроллит страницу до поля ввода.
     */
    MoneyInput.prototype.scrollTo = function () {
        this.root.scrollTo();
    };
    /**
     * Обновляет маску по значению: группирует целую часть в блоки по три символа.
     *
     * @param value Значение
     */
    MoneyInput.prototype.updateMaskByValue = function (value) {
        var _a = getValueParts(value), integerPart = _a[0], fractionPart = _a[1];
        var integerPartLength = Math.max(Math.min(integerPart.length || 1, this.props.integerLength));
        this.maskPattern = splitInteger(new Array(integerPartLength + 1).join('1'))
            .reverse()
            .join(' ');
        if (fractionPart !== undefined && this.props.fractionLength > 0) {
            this.maskPattern += "," + new Array(this.props.fractionLength + 1).join('1');
        }
        this.mask = new mask_1.default(this.maskPattern);
        if (this.root) {
            this.root.getMaskedInputInstance().setMask(this.maskPattern);
        }
    };
    /**
     * Расчитывает максимально допустимую длинну поля ввода.
     */
    MoneyInput.prototype.getMaxLength = function () {
        var maxLength = Math.floor((this.props.integerLength - 1) / INTEGER_PART_SIZE) + this.props.integerLength;
        if (this.props.fractionLength) {
            maxLength += 1 + this.props.fractionLength;
        }
        return maxLength;
    };
    /**
     * Возвращает актуальное значение для рендера.
     */
    MoneyInput.prototype.getValue = function () {
        return this.props.value === undefined ? this.state.value : this.props.value;
    };
    /**
     * Устанавливает каретку поля ввода в новую позицию.
     *
     * @param selection Новое положение каретки
     */
    MoneyInput.prototype.setInputSelection = function (selection) {
        this.root.control.input.selectionStart = selection;
        this.root.control.input.selectionEnd = selection;
        // Android chrome имеет дефект с автоматической установкой каретки
        // при использовании клавиатуры отличной от type="text".
        if (IS_ANDROID) {
            this.setInputSelectionByTimeout(selection);
        }
    };
    /**
     * Устанавливает каретку поля ввода в заданную позицию асинхронно.
     *
     * Во-избежание дефекта с установкой каретки, наблюдаемом в мобильных браузерах,
     * установка происходит асинхронно, с минимальной задержкой,
     * с помощью [setTimeout] обертки.
     *
     * @param selection Положение каретки
     */
    MoneyInput.prototype.setInputSelectionByTimeout = function (selection) {
        var _this = this;
        clearTimeout(this.caretFixTimeout);
        this.caretFixTimeout = setTimeout(function () {
            _this.root.control.input.selectionStart = selection;
            _this.root.control.input.selectionEnd = selection;
        }, 0);
    };
    /**
     * Возвращает значение (невидимый текст) для корректного отображения значка валюты.
     */
    MoneyInput.prototype.getCurrencySpacer = function () {
        return this.mask.format(this.getValue()) || this.props.placeholder;
    };
    MoneyInput.defaultProps = {
        fractionLength: DEFAULT_FRACTION_SIZE,
        integerLength: DEFAULT_INTEGER_SIZE,
        bold: false,
        showCurrency: false,
        currencyCode: 'RUR',
    };
    return MoneyInput;
}(react_1.default.PureComponent));
exports.MoneyInput = MoneyInput;
exports.default = cn_1.withTheme(MoneyInput);

//# sourceMappingURL=money-input.js.map
