import * as tslib_1 from "tslib";
import * as React from 'react';
import { TextField } from '../TextField';
import { autobind, BaseComponent } from '../../../Utilities';
import { clearNext, clearPrev, clearRange, DEFAULT_MASK_FORMAT_CHARS, getLeftFormatIndex, getMaskDisplay, getRightFormatIndex, insertString, parseMask } from './inputMask';
export var DEFAULT_MASK_CHAR = '_';
var inputChangeType;
(function (inputChangeType) {
    inputChangeType[inputChangeType["default"] = 0] = "default";
    inputChangeType[inputChangeType["backspace"] = 1] = "backspace";
    inputChangeType[inputChangeType["delete"] = 2] = "delete";
    inputChangeType[inputChangeType["textPasted"] = 3] = "textPasted";
})(inputChangeType || (inputChangeType = {}));
var MaskedTextField = /** @class */ (function (_super) {
    tslib_1.__extends(MaskedTextField, _super);
    function MaskedTextField(props) {
        var _this = _super.call(this, props) || this;
        /**
         * Tell BaseComponent to bypass resolution of componentRef.
         */
        _this._skipComponentRefResolution = true;
        // Translate mask into charData
        _this._maskCharData = parseMask(props.mask, props.maskFormat);
        // If an initial value is provided, use it to populate the format chars
        props.value && _this.setValue(props.value);
        _this._isFocused = false;
        _this._moveCursorOnMouseUp = false;
        _this.state = {
            displayValue: getMaskDisplay(props.mask, _this._maskCharData, props.maskChar)
        };
        return _this;
    }
    MaskedTextField.prototype.componentWillReceiveProps = function (newProps) {
        if (newProps.mask !== this.props.mask) {
            this._maskCharData = parseMask(newProps.mask, newProps.maskFormat);
            this.state = {
                displayValue: 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.state.maskCursorPosition) {
            this._textField.setSelectionRange(this.state.maskCursorPosition, this.state.maskCursorPosition);
        }
    };
    MaskedTextField.prototype.render = function () {
        return (React.createElement(TextField, tslib_1.__assign({}, this.props, { onFocus: this._onFocus, onBlur: this._onBlur, onMouseDown: this._onMouseDown, onMouseUp: this._onMouseUp, onChanged: this._onInputChange, onBeforeChange: this._onBeforeChange, onKeyDown: this._onKeyDown, onPaste: this._onPaste, value: this.state.displayValue, ref: this._resolveRef('_textField') })));
    };
    Object.defineProperty(MaskedTextField.prototype, "value", {
        /**
         * @return 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 () {
        this._textField && this._textField.focus();
    };
    MaskedTextField.prototype.select = function () {
        this._textField && this._textField.select();
    };
    MaskedTextField.prototype.setSelectionStart = function (value) {
        this._textField && this._textField.setSelectionStart(value);
    };
    MaskedTextField.prototype.setSelectionEnd = function (value) {
        this._textField && this._textField.setSelectionEnd(value);
    };
    MaskedTextField.prototype.setSelectionRange = function (start, end) {
        this._textField && this._textField.setSelectionRange(start, end);
    };
    Object.defineProperty(MaskedTextField.prototype, "selectionStart", {
        get: function () {
            return this._textField && this._textField.selectionStart !== null ? this._textField.selectionStart : -1;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MaskedTextField.prototype, "selectionEnd", {
        get: function () {
            return this._textField && this._textField.selectionEnd ? this._textField.selectionEnd : -1;
        },
        enumerable: true,
        configurable: true
    });
    MaskedTextField.prototype._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;
            }
        }
    };
    MaskedTextField.prototype._onBlur = function (event) {
        if (this.props.onBlur) {
            this.props.onBlur(event);
        }
        this._isFocused = false;
        this._moveCursorOnMouseUp = true;
    };
    MaskedTextField.prototype._onMouseDown = function (event) {
        if (this.props.onMouseDown) {
            this.props.onMouseDown(event);
        }
        if (!this._isFocused) {
            this._moveCursorOnMouseUp = true;
        }
    };
    MaskedTextField.prototype._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;
                }
            }
        }
    };
    MaskedTextField.prototype._onBeforeChange = function (value) {
        if (this.props.onBeforeChange) {
            this.props.onBeforeChange(value);
        }
        if (this._changeSelectionData === null) {
            this._changeSelectionData = {
                changeType: inputChangeType.default,
                selectionStart: this._textField.selectionStart !== null ? this._textField.selectionStart : -1,
                selectionEnd: this._textField.selectionEnd !== null ? this._textField.selectionEnd : -1
            };
        }
    };
    MaskedTextField.prototype._onInputChange = function (value) {
        if (this.props.onChanged) {
            this.props.onChanged(value);
        }
        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 === inputChangeType.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 = clearRange(this._maskCharData, selectionStart, charsSelected);
            }
            cursorPos = insertString(this._maskCharData, startPos, pastedString);
        }
        else if (changeType === inputChangeType.delete || changeType === inputChangeType.backspace) {
            // isDel is true If the characters are removed LTR, otherwise RTL
            var isDel = changeType === inputChangeType.delete, charCount = selectionEnd - selectionStart;
            if (charCount) {
                // charCount is > 0 if range was deleted
                this._maskCharData = clearRange(this._maskCharData, selectionStart, charCount);
                cursorPos = getRightFormatIndex(this._maskCharData, selectionStart);
            }
            else {
                // If charCount === 0, there was no selection and a single character was deleted
                if (isDel) {
                    this._maskCharData = clearNext(this._maskCharData, selectionStart);
                    cursorPos = getRightFormatIndex(this._maskCharData, selectionStart);
                }
                else {
                    this._maskCharData = clearPrev(this._maskCharData, selectionStart);
                    cursorPos = 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 = 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 = clearRange(this._maskCharData, startPos, selectCount);
            // Insert the printed character
            cursorPos = insertString(this._maskCharData, startPos, enteredString);
        }
        this._changeSelectionData = null;
        this.setState({
            displayValue: getMaskDisplay(this.props.mask, this._maskCharData, this.props.maskChar),
            maskCursorPosition: cursorPos
        });
    };
    MaskedTextField.prototype._onKeyDown = function (event) {
        if (this.props.onKeyDown) {
            this.props.onKeyDown(event);
        }
        this._changeSelectionData = null;
        if (this._textField.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 === 8 /* backspace */ || keyCode === 46 /* del */) {
                var selectionStart = event.target.selectionStart, selectionEnd = event.target.selectionEnd;
                // Check if backspace or delete press is valid.
                if (!(keyCode === 8 /* backspace */ && selectionEnd && selectionEnd > 0) &&
                    !(keyCode === 46 /* del */ && selectionStart !== null && selectionStart < this._textField.value.length)) {
                    return;
                }
                this._changeSelectionData = {
                    changeType: keyCode === 8 /* backspace */ ? inputChangeType.backspace : inputChangeType.delete,
                    selectionStart: selectionStart !== null ? selectionStart : -1,
                    selectionEnd: selectionEnd !== null ? selectionEnd : -1
                };
            }
        }
    };
    MaskedTextField.prototype._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: inputChangeType.textPasted,
            selectionStart: selectionStart !== null ? selectionStart : -1,
            selectionEnd: selectionEnd !== null ? selectionEnd : -1
        };
    };
    MaskedTextField.defaultProps = {
        maskChar: DEFAULT_MASK_CHAR,
        maskFormat: DEFAULT_MASK_FORMAT_CHARS
    };
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onFocus", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onBlur", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onMouseDown", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onMouseUp", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onBeforeChange", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onInputChange", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onKeyDown", null);
    tslib_1.__decorate([
        autobind
    ], MaskedTextField.prototype, "_onPaste", null);
    return MaskedTextField;
}(BaseComponent));
export { MaskedTextField };
//# sourceMappingURL=MaskedTextField.js.map