define(["require", "exports", "tslib", "react", "../TextField", "../../../Utilities", "./inputMask"], function (require, exports, tslib_1, React, TextField_1, Utilities_1, inputMask_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.DEFAULT_MASK_CHAR = '_';
    var MaskedTextField = /** @class */ (function (_super) {
        tslib_1.__extends(MaskedTextField, _super);
        function MaskedTextField(props) {
            var _this = _super.call(this, props) || this;
            _this._textField = React.createRef();
            _this._onFocus = function (event) {
                if (_this.props.onFocus) {
                    _this.props.onFocus(event);
                }
                _this._isFocused = true;
                // Move the cursor position to the leftmost unfilled position
                for (var i = 0; i < _this._maskCharData.length; i++) {
                    if (!_this._maskCharData[i].value) {
                        _this.setState({
                            maskCursorPosition: _this._maskCharData[i].displayIndex
                        });
                        break;
                    }
                }
            };
            _this._onBlur = function (event) {
                if (_this.props.onBlur) {
                    _this.props.onBlur(event);
                }
                _this._isFocused = false;
                _this._moveCursorOnMouseUp = true;
            };
            _this._onMouseDown = function (event) {
                if (_this.props.onMouseDown) {
                    _this.props.onMouseDown(event);
                }
                if (!_this._isFocused) {
                    _this._moveCursorOnMouseUp = true;
                }
            };
            _this._onMouseUp = function (event) {
                if (_this.props.onMouseUp) {
                    _this.props.onMouseUp(event);
                }
                // Move the cursor on mouseUp after focusing the textField
                if (_this._moveCursorOnMouseUp) {
                    _this._moveCursorOnMouseUp = false;
                    // Move the cursor position to the rightmost unfilled position
                    for (var i = 0; i < _this._maskCharData.length; i++) {
                        if (!_this._maskCharData[i].value) {
                            _this.setState({
                                maskCursorPosition: _this._maskCharData[i].displayIndex
                            });
                            break;
                        }
                    }
                }
            };
            _this._onInputChange = function (ev, value) {
                var textField = _this._textField.current;
                if (_this._changeSelectionData === null && textField) {
                    _this._changeSelectionData = {
                        changeType: 'default',
                        selectionStart: textField.selectionStart !== null ? textField.selectionStart : -1,
                        selectionEnd: textField.selectionEnd !== null ? textField.selectionEnd : -1
                    };
                }
                if (!_this._changeSelectionData) {
                    return;
                }
                var displayValue = _this.state.displayValue;
                // The initial value of cursorPos does not matter
                var cursorPos = 0;
                var _a = _this._changeSelectionData, changeType = _a.changeType, selectionStart = _a.selectionStart, selectionEnd = _a.selectionEnd;
                if (changeType === 'textPasted') {
                    var charsSelected = selectionEnd - selectionStart, charCount = value.length + charsSelected - displayValue.length, startPos = selectionStart, pastedString = value.substr(startPos, charCount);
                    // Clear any selected characters
                    if (charsSelected) {
                        _this._maskCharData = inputMask_1.clearRange(_this._maskCharData, selectionStart, charsSelected);
                    }
                    cursorPos = inputMask_1.insertString(_this._maskCharData, startPos, pastedString);
                }
                else if (changeType === 'delete' || changeType === 'backspace') {
                    // isDel is true If the characters are removed LTR, otherwise RTL
                    var isDel = changeType === 'delete', charCount = selectionEnd - selectionStart;
                    if (charCount) {
                        // charCount is > 0 if range was deleted
                        _this._maskCharData = inputMask_1.clearRange(_this._maskCharData, selectionStart, charCount);
                        cursorPos = inputMask_1.getRightFormatIndex(_this._maskCharData, selectionStart);
                    }
                    else {
                        // If charCount === 0, there was no selection and a single character was deleted
                        if (isDel) {
                            _this._maskCharData = inputMask_1.clearNext(_this._maskCharData, selectionStart);
                            cursorPos = inputMask_1.getRightFormatIndex(_this._maskCharData, selectionStart);
                        }
                        else {
                            _this._maskCharData = inputMask_1.clearPrev(_this._maskCharData, selectionStart);
                            cursorPos = inputMask_1.getLeftFormatIndex(_this._maskCharData, selectionStart);
                        }
                    }
                }
                else if (value.length > displayValue.length) {
                    // This case is if the user added characters
                    var charCount = value.length - displayValue.length, startPos = selectionEnd - charCount, enteredString = value.substr(startPos, charCount);
                    cursorPos = inputMask_1.insertString(_this._maskCharData, startPos, enteredString);
                }
                else if (value.length <= displayValue.length) {
                    /**
                     * This case is reached only if the user has selected a block of 1 or more
                     * characters and input a character replacing the characters they've selected.
                     */
                    var charCount = 1, selectCount = displayValue.length + charCount - value.length, startPos = selectionEnd - charCount, enteredString = value.substr(startPos, charCount);
                    // Clear the selected range
                    _this._maskCharData = inputMask_1.clearRange(_this._maskCharData, startPos, selectCount);
                    // Insert the printed character
                    cursorPos = inputMask_1.insertString(_this._maskCharData, startPos, enteredString);
                }
                _this._changeSelectionData = null;
                var newValue = inputMask_1.getMaskDisplay(_this.props.mask, _this._maskCharData, _this.props.maskChar);
                _this.setState({
                    displayValue: newValue,
                    maskCursorPosition: cursorPos
                });
                // Perform onChange after input has been processed. Return value is expected to be the displayed text
                if (_this.props.onChange) {
                    _this.props.onChange(ev, newValue);
                }
            };
            _this._onKeyDown = function (event) {
                var current = _this._textField.current;
                if (_this.props.onKeyDown) {
                    _this.props.onKeyDown(event);
                }
                _this._changeSelectionData = null;
                if (current && current.value) {
                    var keyCode = event.keyCode, ctrlKey = event.ctrlKey, metaKey = event.metaKey;
                    // Ignore ctrl and meta keydown
                    if (ctrlKey || metaKey) {
                        return;
                    }
                    // On backspace or delete, store the selection and the keyCode
                    if (keyCode === Utilities_1.KeyCodes.backspace || keyCode === Utilities_1.KeyCodes.del) {
                        var selectionStart = event.target.selectionStart, selectionEnd = event.target.selectionEnd;
                        // Check if backspace or delete press is valid.
                        if (!(keyCode === Utilities_1.KeyCodes.backspace && selectionEnd && selectionEnd > 0) &&
                            !(keyCode === Utilities_1.KeyCodes.del && selectionStart !== null && selectionStart < current.value.length)) {
                            return;
                        }
                        _this._changeSelectionData = {
                            changeType: keyCode === Utilities_1.KeyCodes.backspace ? 'backspace' : 'delete',
                            selectionStart: selectionStart !== null ? selectionStart : -1,
                            selectionEnd: selectionEnd !== null ? selectionEnd : -1
                        };
                    }
                }
            };
            _this._onPaste = function (event) {
                if (_this.props.onPaste) {
                    _this.props.onPaste(event);
                }
                var selectionStart = event.target.selectionStart, selectionEnd = event.target.selectionEnd;
                // Store the paste selection range
                _this._changeSelectionData = {
                    changeType: 'textPasted',
                    selectionStart: selectionStart !== null ? selectionStart : -1,
                    selectionEnd: selectionEnd !== null ? selectionEnd : -1
                };
            };
            Utilities_1.initializeComponentRef(_this);
            // Translate mask into charData
            _this._maskCharData = inputMask_1.parseMask(props.mask, props.maskFormat);
            // If an initial value is provided, use it to populate the format chars
            props.value !== undefined && _this.setValue(props.value);
            _this._isFocused = false;
            _this._moveCursorOnMouseUp = false;
            _this.state = {
                displayValue: inputMask_1.getMaskDisplay(props.mask, _this._maskCharData, props.maskChar)
            };
            return _this;
        }
        // tslint:disable-next-line function-name
        MaskedTextField.prototype.UNSAFE_componentWillReceiveProps = function (newProps) {
            if (newProps.mask !== this.props.mask || newProps.value !== this.props.value) {
                this._maskCharData = inputMask_1.parseMask(newProps.mask, newProps.maskFormat);
                newProps.value !== undefined && this.setValue(newProps.value);
                this.setState({
                    displayValue: inputMask_1.getMaskDisplay(newProps.mask, this._maskCharData, newProps.maskChar)
                });
            }
        };
        MaskedTextField.prototype.componentDidUpdate = function () {
            // Move the cursor to the start of the mask format on update
            if (this._isFocused && this.state.maskCursorPosition !== undefined && this._textField.current) {
                this._textField.current.setSelectionRange(this.state.maskCursorPosition, this.state.maskCursorPosition);
            }
        };
        MaskedTextField.prototype.render = function () {
            return (React.createElement(TextField_1.TextField, tslib_1.__assign({}, this.props, { onFocus: this._onFocus, onBlur: this._onBlur, onMouseDown: this._onMouseDown, onMouseUp: this._onMouseUp, onChange: this._onInputChange, onKeyDown: this._onKeyDown, onPaste: this._onPaste, value: this.state.displayValue || '', componentRef: this._textField })));
        };
        Object.defineProperty(MaskedTextField.prototype, "value", {
            /**
             * @returns The value of all filled format characters or undefined if not all format characters are filled
             */
            get: function () {
                var value = '';
                for (var i = 0; i < this._maskCharData.length; i++) {
                    if (!this._maskCharData[i].value) {
                        return undefined;
                    }
                    value += this._maskCharData[i].value;
                }
                return value;
            },
            enumerable: true,
            configurable: true
        });
        MaskedTextField.prototype.setValue = function (newValue) {
            var valueIndex = 0, charDataIndex = 0;
            while (valueIndex < newValue.length && charDataIndex < this._maskCharData.length) {
                // Test if the next character in the new value fits the next format character
                var testVal = newValue[valueIndex];
                if (this._maskCharData[charDataIndex].format.test(testVal)) {
                    this._maskCharData[charDataIndex].value = testVal;
                    charDataIndex++;
                }
                valueIndex++;
            }
        };
        MaskedTextField.prototype.focus = function () {
            var current = this._textField.current;
            current && current.focus();
        };
        MaskedTextField.prototype.blur = function () {
            var current = this._textField.current;
            current && current.blur();
        };
        MaskedTextField.prototype.select = function () {
            var current = this._textField.current;
            current && current.select();
        };
        MaskedTextField.prototype.setSelectionStart = function (value) {
            var current = this._textField.current;
            current && current.setSelectionStart(value);
        };
        MaskedTextField.prototype.setSelectionEnd = function (value) {
            var current = this._textField.current;
            current && current.setSelectionEnd(value);
        };
        MaskedTextField.prototype.setSelectionRange = function (start, end) {
            var current = this._textField.current;
            current && current.setSelectionRange(start, end);
        };
        Object.defineProperty(MaskedTextField.prototype, "selectionStart", {
            get: function () {
                var current = this._textField.current;
                return current && current.selectionStart !== null ? current.selectionStart : -1;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MaskedTextField.prototype, "selectionEnd", {
            get: function () {
                var current = this._textField.current;
                return current && current.selectionEnd ? current.selectionEnd : -1;
            },
            enumerable: true,
            configurable: true
        });
        MaskedTextField.defaultProps = {
            maskChar: exports.DEFAULT_MASK_CHAR,
            maskFormat: inputMask_1.DEFAULT_MASK_FORMAT_CHARS
        };
        return MaskedTextField;
    }(React.Component));
    exports.MaskedTextField = MaskedTextField;
});
//# sourceMappingURL=MaskedTextField.js.map