"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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InputAutocomplete = 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 menu_1 = __importDefault(require("../menu/menu"));
var popup_1 = __importDefault(require("../popup/popup"));
var resize_sensor_1 = require("../resize-sensor/resize-sensor");
var keyboard_code_1 = __importDefault(require("../lib/keyboard-code"));
var performance_1 = __importDefault(require("../performance"));
var scroll_to_1 = __importDefault(require("../lib/scroll-to"));
var vars_1 = require("../vars");
var input_1 = __importDefault(require("../input/input"));
/**
 * Компонент поля для ввода с автокомплитом.
 *
 * @extends Input
 */
var InputAutocomplete = /** @class */ (function (_super) {
    __extends(InputAutocomplete, _super);
    function InputAutocomplete() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.cn = bem_react_classname_1.createCn('input');
        _this.state = {
            value: _this.props.defaultValue || '',
            inputFocused: false,
            menuFocused: false,
            popupStyles: {},
            highlightedItem: null,
        };
        _this.blurTimeout = null;
        _this.inputFocusTimeout = null;
        _this.handleItemCheck = function (checkedItemsValues, event) {
            var checkedItemValue = checkedItemsValues.length ? checkedItemsValues[0] : _this.state.checkedItemValue;
            var checkedItem = _this.getCheckedOption(_this.props.options, checkedItemValue);
            var newValue = checkedItem
                ? (checkedItem.text || checkedItem.value)
                : _this.state.value;
            if (_this.props.onItemSelect) {
                _this.props.onItemSelect(checkedItem);
            }
            if (_this.props.updateValueOnItemSelect) {
                _this.setState({ value: newValue });
                if (_this.props.onChange) {
                    _this.props.onChange(newValue, event);
                }
            }
            if (_this.inputFocusTimeout) {
                clearTimeout(_this.inputFocusTimeout);
            }
            if (_this.inputBlurTimeout) {
                clearTimeout(_this.inputBlurTimeout);
            }
            if (_this.props.closeOnSelect) {
                _this.inputBlurTimeout = setTimeout(function () { return _this.input.blur(); }, 0);
            }
            else {
                _this.inputFocusTimeout = setTimeout(function () {
                    _this.input.focus();
                    _this.input.setSelectionRange(newValue.length);
                }, 0);
            }
        };
        _this.handleChange = function (value, event) {
            _this.setState({ value: value });
            if (_this.props.onChange) {
                _this.props.onChange(value, event);
            }
        };
        _this.handleInputFocus = function (event) {
            if (_this.blurTimeout) {
                clearTimeout(_this.blurTimeout);
                _this.blurTimeout = null;
            }
            _this.solveFocused(event);
            _this.setState({
                highlightedItem: null,
            });
        };
        _this.handleInputBlur = function (event) {
            if (_this.blurTimeout) {
                clearTimeout(_this.blurTimeout);
            }
            event.persist();
            _this.blurTimeout = setTimeout(function () {
                _this.solveFocused(event);
                _this.blurTimeout = null;
            }, 0);
        };
        _this.handleMenuFocus = function (event) {
            if (_this.blurTimeout) {
                clearTimeout(_this.blurTimeout);
                _this.blurTimeout = null;
            }
            _this.solveFocused(event);
        };
        _this.handleMenuBlur = function (event) {
            if (_this.blurTimeout) {
                clearTimeout(_this.blurTimeout);
            }
            event.persist();
            _this.blurTimeout = setTimeout(function () {
                _this.solveFocused(event);
                _this.blurTimeout = null;
            }, 0);
        };
        _this.handleClickOutside = function () {
            if (_this.props.onClickOutside) {
                _this.props.onClickOutside();
            }
        };
        _this.handleKeyDown = function (event) {
            switch (event.which) {
                case keyboard_code_1.default.DOWN_ARROW: {
                    event.preventDefault();
                    var posX = window.pageXOffset;
                    var posY = window.pageYOffset;
                    if (_this.menu) {
                        _this.menu.focus();
                    }
                    window.scrollTo(posX, posY);
                    break;
                }
                case keyboard_code_1.default.ESCAPE: {
                    _this.input.blur();
                    break;
                }
            }
            if (_this.props.onKeyDown) {
                _this.props.onKeyDown(event);
            }
        };
        _this.handleHighlightedItem = function (highlightedItem) {
            _this.setState({
                highlightedItem: highlightedItem,
            });
        };
        _this.handleMenuKeyDown = function (event, highlightedItem) {
            switch (event.which) {
                case keyboard_code_1.default.DOWN_ARROW:
                case keyboard_code_1.default.UP_ARROW:
                    event.preventDefault();
                    _this.syncKeyboardNavigationWithScroll(highlightedItem);
                    break;
                case keyboard_code_1.default.ESCAPE:
                    _this.input.focus();
                    break;
            }
            if (_this.props.onKeyDown) {
                _this.props.onKeyDown(event);
            }
        };
        _this.updatePopupStyles = function () {
            var input = _this.input.getNode();
            var inputWidth = input.getBoundingClientRect().width;
            var popupStyles = { minWidth: inputWidth };
            if (_this.props.equalPopupWidth) {
                popupStyles.maxWidth = inputWidth;
            }
            _this.setState({
                popupStyles: popupStyles,
            });
        };
        return _this;
    }
    InputAutocomplete.prototype.componentDidMount = function () {
        this.updatePopupTarget();
        this.updatePopupStyles();
    };
    InputAutocomplete.prototype.componentDidUpdate = function () {
        this.updatePopupTarget();
        this.updatePopupStyles();
    };
    InputAutocomplete.prototype.componentWillUnmount = function () {
        if (this.blurTimeout) {
            clearTimeout(this.blurTimeout);
            this.blurTimeout = null;
        }
        if (this.inputBlurTimeout) {
            clearTimeout(this.inputBlurTimeout);
            this.inputBlurTimeout = null;
        }
        if (this.inputFocusTimeout) {
            clearTimeout(this.inputFocusTimeout);
            this.inputFocusTimeout = null;
        }
    };
    InputAutocomplete.prototype.render = function () {
        var _this = this;
        var value = this.props.value === undefined ? this.state.value : this.props.value;
        var props = __assign(__assign({}, this.props), { ref: function (input) {
                _this.input = input;
            }, className: this.cn({
                focused: this.state.inputFocused || this.state.menuFocused,
                'has-autocomplete': true,
            }), autocomplete: this.props.autocomplete || false, value: value, onChange: this.handleChange, onFocus: this.handleInputFocus, onBlur: this.handleInputBlur, onKeyDown: this.handleKeyDown });
        return (react_1.default.createElement("div", { className: this.cn('autocomplete-case', { width: this.props.width }), "data-test-id": this.props['data-test-id'] },
            react_1.default.createElement(input_1.default, __assign({}, props)),
            this.renderPopup()));
    };
    InputAutocomplete.prototype.renderPopup = function () {
        var _this = this;
        var formattedOptionsList = this.props.options
            ? this.formatOptionsList(this.props.options)
            : [];
        var opened = this.props.opened === undefined
            ? (this.state.inputFocused || this.state.menuFocused)
            : this.props.opened;
        if (this.props.options.length === 0) {
            this.popup = null;
            return null;
        }
        if (this.props.renderPopupOnFocus && !opened) {
            return null;
        }
        return [
            react_1.default.createElement(resize_sensor_1.ResizeSensor, { onResize: this.updatePopupStyles, key: "popup-sensor" }),
            react_1.default.createElement(popup_1.default, { className: this.cn('popup', { custom: this.props.popupClassName }), size: this.props.size, ref: function (popup) {
                    _this.popup = popup;
                }, for: this.props.name, visible: opened, onClickOutside: this.handleClickOutside, target: "anchor", directions: this.props.directions, height: this.props.popupMaxHeight ? 'default' : 'adaptive', padded: false, minWidth: this.state.popupStyles.minWidth, maxWidth: this.state.popupStyles.maxWidth, key: "popup", maxHeight: this.props.popupMaxHeight },
                react_1.default.createElement(menu_1.default, { ref: function (menu) {
                        _this.menu = menu;
                    }, className: this.cn('menu'), size: this.props.size, mode: "radio-check", content: formattedOptionsList, checkedItems: [], onItemCheck: this.handleItemCheck, autoFocusFirstItem: true, highlightedItem: this.state.highlightedItem, onHighlightItem: this.handleHighlightedItem, onFocus: this.handleMenuFocus, onBlur: this.handleMenuBlur, onKeyDown: this.handleMenuKeyDown })),
        ];
    };
    /**
     * Устанавливает фокус на поле ввода.
     */
    InputAutocomplete.prototype.focus = function () {
        this.input.focus();
    };
    /**
     * Убирает фокус с поля ввода.
     */
    InputAutocomplete.prototype.blur = function () {
        this.input.blur();
    };
    /**
     * Скроллит страницу до поля ввода.
     */
    InputAutocomplete.prototype.scrollTo = function () {
        this.input.scrollTo();
    };
    /**
     * Определяет является ли весь компонент в фокусе на событиях onFocus/onBlur.
     *
     * @param event Событие focus/blur, которое будет проброшено в обработчик onFocus/onBlur
     */
    InputAutocomplete.prototype.solveFocused = function (event) {
        var currentFocused = this.state.inputFocused || this.state.menuFocused;
        var focusedElement = document.activeElement;
        var newState = {
            inputFocused: (focusedElement === this.input.getControl()),
            menuFocused: this.menu
                ? (this.menu.getNode() === focusedElement || this.menu.getNode().contains(focusedElement))
                : false,
        };
        var newFocused = newState.inputFocused || newState.menuFocused;
        if (currentFocused !== newFocused) {
            if (newFocused) {
                if (this.props.onFocus) {
                    this.props.onFocus(event);
                }
            }
            else if (this.props.onBlur) {
                this.props.onBlur(event);
            }
        }
        this.setState(newState);
    };
    InputAutocomplete.prototype.formatOptionsList = function (options) {
        var _this = this;
        return (options.map(function (option) {
            if (option.type === 'group' && !!option.content) {
                var content = _this.formatOptionsList(option.content);
                return ({
                    type: 'group',
                    title: option.title,
                    content: content,
                });
            }
            return ({
                key: option.key || option.value,
                value: option.value,
                content: option.description || option.value,
                props: option.props,
            });
        }));
    };
    InputAutocomplete.prototype.getCheckedOption = function (options, value) {
        var _this = this;
        var result = null;
        options.find(function (option) {
            if (option.type === 'group' && !!option.content) {
                var findInGroup = _this.getCheckedOption(option.content, value);
                if (findInGroup) {
                    result = findInGroup;
                    return true;
                }
            }
            else if (option.value === value) {
                result = option;
                return true;
            }
            return false;
        });
        return result;
    };
    InputAutocomplete.prototype.updatePopupTarget = function () {
        if (this.popup) {
            this.popup.setTarget(this.input.getBoxNode());
        }
    };
    /**
     * @param highlightedItem Выбранный пункт меню
     */
    InputAutocomplete.prototype.syncKeyboardNavigationWithScroll = function (highlightedItem) {
        var element = highlightedItem.getNode();
        var container = this.popup.getInnerNode();
        var correction = element.offsetHeight;
        if (element.offsetTop + correction > container.scrollTop + container.offsetHeight) {
            scroll_to_1.default({
                container: container,
                targetY: element.offsetTop,
                duration: vars_1.SCROLL_TO_NORMAL_DURATION,
            });
        }
        else if (element.offsetTop < container.scrollTop) {
            scroll_to_1.default({
                container: container,
                targetY: (element.offsetTop - container.offsetHeight) + correction,
                duration: vars_1.SCROLL_TO_NORMAL_DURATION,
            });
        }
    };
    InputAutocomplete.defaultProps = {
        disabled: false,
        size: 'm',
        width: 'default',
        options: [],
        updateValueOnItemSelect: true,
        directions: ['bottom-left', 'bottom-right', 'top-left', 'top-right'],
        equalPopupWidth: false,
        closeOnSelect: false,
        renderPopupOnFocus: false,
    };
    InputAutocomplete = __decorate([
        performance_1.default(true)
    ], InputAutocomplete);
    return InputAutocomplete;
}(react_1.default.Component));
exports.InputAutocomplete = InputAutocomplete;
exports.default = cn_1.withTheme(InputAutocomplete);

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