var _a;
import { __awaiter, __decorate, __extends, __generator } from "tslib";
import Vue from 'vue';
import Component from 'vue-class-component';
import { Emit, Model, Prop, Watch } from 'vue-property-decorator';
import { POPUP_NAME as DIRECTIVE_POPUP_NAME } from '../../directives/directive-names';
import { MPopupDirective } from '../../directives/popup/popup';
import { InputLabel } from '../../mixins/input-label/input-label';
import { InputPopup } from '../../mixins/input-popup/input-popup';
import { InputState } from '../../mixins/input-state/input-state';
import { InputWidth } from '../../mixins/input-width/input-width';
import { MediaQueries } from '../../mixins/media-queries/media-queries';
import MediaQueriesPlugin from '../../utils/media-queries/media-queries';
import { normalizeString } from '../../utils/str/str';
import UserAgentUtil from '../../utils/user-agent/user-agent';
import uuid from '../../utils/uuid/uuid';
import { MButton } from '../button/button';
import { DROPDOWN_ITEM_NAME, DROPDOWN_NAME } from '../component-names';
import { MIconButton } from '../icon-button/icon-button';
import { MIcon } from '../icon/icon';
import { MInputStyle } from '../input-style/input-style';
import { MPopup } from '../popup/popup';
import { MValidationMessage } from '../validation-message/validation-message';
import { InputManagement } from './../../mixins/input-management/input-management';
import { BaseDropdown, MDropdownItem } from './dropdown-item/dropdown-item';
import WithRender from './dropdown.html?style=./dropdown.scss';
var DROPDOWN_STYLE_TRANSITION = 'max-height 0.3s ease';
var MDropdown = /** @class */ (function (_super) {
    __extends(MDropdown, _super);
    function MDropdown() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.listboxId = "listboxId-" + uuid.generate();
        _this.popupId = "popup-" + uuid.generate();
        _this.internalFilter = '';
        _this.internalFilterRegExp = / /;
        _this.internalItems = [];
        _this.internalSelectedText = '';
        _this.internalIsFocus = false;
        _this.focusedIndex = -1;
        _this.internalOpen = false;
        _this.dirty = false;
        return _this;
    }
    MDropdown.prototype.onForceOpenUpdate = function () {
        if (this.forceOpen) {
            this.internalOpen = this.forceOpen;
        }
    };
    Object.defineProperty(MDropdown.prototype, "inputAriaActivedescendant", {
        get: function () {
            return this.focusedIndex >= 0 && this.open ? this.internalNavigationItems[this.focusedIndex].id : '';
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.matchFilter = function (text) {
        var result = true;
        if (text !== undefined && this.dirty && (this.internalFilterRegExp)) {
            result = this.internalFilterRegExp.test(text);
        }
        return result;
    };
    MDropdown.prototype.onFocusIn = function () {
        if (!this.filterable) {
            this.$refs.input.setSelectionRange(0, 0);
        }
        this.internalIsFocus = true;
    };
    MDropdown.prototype.onFocusOut = function () {
        this.internalIsFocus = false;
    };
    Object.defineProperty(MDropdown.prototype, "filterableDesktop", {
        get: function () {
            return this.filterable && this.as().isMqMinS;
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.groupHasItems = function (group) {
        return this.internalItems.some(function (i) {
            return i.group === group;
        });
    };
    MDropdown.prototype.created = function () {
        this.setInternalValue(this.value);
    };
    MDropdown.prototype.mounted = function () {
        if (this.focus) {
            this.focusChanged(this.focus);
        }
    };
    MDropdown.prototype.beforeDestroy = function () {
        if (this.observer) {
            this.observer.disconnect();
        }
    };
    Object.defineProperty(MDropdown.prototype, "open", {
        get: function () {
            return this.internalOpen;
        },
        set: function (value) {
            if (value && value !== this.internalOpen) {
                this.focusedIndex = -1;
            }
            if (this.as().active) {
                this.internalOpen = value;
            }
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.onOpen = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.$nextTick()];
                    case 1:
                        _a.sent();
                        requestAnimationFrame(function () {
                            var inputEl = _this.$refs.input;
                            var researchInputEl = _this.$refs.researchInput;
                            if (!(_this.filterable && _this.as().isMqMaxS)) {
                                _this.as().internalIsFocus = true;
                                inputEl.focus();
                            }
                            else if (researchInputEl) {
                                researchInputEl.focus();
                            }
                        });
                        this.focusSelected();
                        this.scrollToFocused();
                        return [2 /*return*/];
                }
            });
        });
    };
    MDropdown.prototype.onClose = function () {
        var hasMatch = this.matchFilterTextToValue();
        this.internalFilter = '';
        this.dirty = false;
        this.internalFilterRegExp = / /;
        if (this.clearInvalidSelectionOnClose && !hasMatch && this.selectedText === '') {
            this.$emit('input', '');
            this.setModel('', true);
        }
    };
    MDropdown.prototype.setInternalValue = function (value) {
        this.setModel(value, false);
    };
    MDropdown.prototype.focusChanged = function (focus) {
        if (focus && !this.as().isDisabled) {
            this.selectText();
        }
        else {
            if (!this.isAndroid) {
                this.$refs.input.blur();
            }
            this.open = false;
        }
    };
    MDropdown.prototype.matchFilterTextToValue = function () {
        var _this = this;
        if (this.filterable && this.internalFilter !== '') {
            var value_1 = '';
            this.internalItems.every(function (item) {
                if (item.propLabel && normalizeString(item.propLabel) === normalizeString(_this.internalFilter)) {
                    value_1 = item.value;
                    return false;
                }
                return true;
            });
            if (value_1 !== '') {
                this.model = value_1;
                return true;
            }
        }
        return false;
    };
    Object.defineProperty(MDropdown.prototype, "model", {
        get: function () {
            return this.value === undefined ? this.as().internalValue : this.value;
        },
        set: function (value) {
            this.setModel(value, true);
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.setModel = function (value, emit) {
        this.as().internalValue = value;
        if (emit) {
            this.$emit('change', value);
        }
        this.dirty = false;
        if (value !== '') {
            this.open = false;
        }
        this.setInputWidth();
    };
    Object.defineProperty(MDropdown.prototype, "internalPlaceholder", {
        get: function () {
            return this.as().isReadonly ? '' : this.as().placeholder;
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.portalMounted = function () {
        var _this = this;
        this.buildItemsMap();
        this.observer = new MutationObserver(function () {
            _this.buildItemsMap();
        });
        if (this.$refs.items) {
            // todo: mobile
            this.observer.observe(this.$refs.items, { subtree: true, childList: true });
        }
    };
    MDropdown.prototype.setInputWidth = function () {
        var _this = this;
        this.$nextTick(function () {
            if (_this.$refs.mInputStyle) {
                _this.$refs.mInputStyle.setInputWidth();
            }
        });
    };
    Object.defineProperty(MDropdown.prototype, "inputStyletWidth", {
        get: function () {
            return this.as().inputWidth === 'auto' && this.as().maxWidth === 'none' ? 'auto' : '100%';
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "focused", {
        get: function () {
            return this.focusedIndex > -1 ? this.internalNavigationItems[this.focusedIndex].value : this.model;
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.onIsMqMaxS = function (value, old) {
        var _this = this;
        if (value !== old) {
            this.$nextTick(function () { return _this.buildItemsMap(); });
        }
    };
    Object.defineProperty(MDropdown.prototype, "selectedText", {
        get: function () {
            var _this = this;
            var result = '';
            if (this.dirty || this.internalFilter) {
                result = this.internalFilter;
            }
            else if (this.internalItems.every(function (item) {
                if (item.value === _this.model) {
                    result = item.propLabel;
                    return false;
                }
                return true;
            })) {
                result = '';
            }
            return result;
        },
        set: function (value) {
            this.dirty = true;
            if (this.clearModelOnSelectedText) {
                this.$emit('change', '');
                this.as().internalValue = value;
            }
            this.internalFilter = value;
            var parsedQuery = normalizeString(this.internalFilter).replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, '\\$1');
            this.internalFilterRegExp = new RegExp(parsedQuery, 'i');
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "isEmpty", {
        get: function () {
            return !this.open && !this.as().hasValue && !Boolean(this.internalPlaceholder);
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.buildItemsMap = function () {
        this.focusedIndex = -1;
        // all visible items
        var items = [];
        // items that can be reached with the keyboard (!disabled)
        var navigation = [];
        this.$refs.popup.$children[0].$children.forEach(function (item) {
            if (item instanceof MDropdownItem && !item.inactive && !item.filtered) {
                items.push(item);
                if (!item.disabled) {
                    navigation.push(item);
                }
            }
        });
        this.internalItems = items;
        this.internalNavigationItems = navigation;
        this.focusSelected();
    };
    Object.defineProperty(MDropdown.prototype, "propTextNoData", {
        get: function () {
            return (this.textNoData ? this.textNoData : this.$i18n.translate('m-dropdown:no-data'));
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "propTextNoMatch", {
        get: function () {
            return (this.textNoMatch ? this.textNoMatch : this.$i18n.translate('m-dropdown:no-result'));
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "hasItems", {
        get: function () {
            return this.internalItems.length > 0;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "inactive", {
        get: function () {
            return this.as().isDisabled || this.as().isReadonly || this.as().isWaiting;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "hasFooterSlot", {
        get: function () {
            return !!this.$slots.footer;
        },
        enumerable: false,
        configurable: true
    });
    MDropdown.prototype.onKeydownHome = function ($event) {
        if (!this.hasItems || this.focusedIndex < 0 || !this.open) {
            return;
        }
        this.focusedIndex = 0;
        this.scrollToFocused();
    };
    MDropdown.prototype.onKeydownEnd = function ($event) {
        if (!this.hasItems || this.focusedIndex < 0 || !this.open) {
            return;
        }
        this.focusedIndex = this.internalNavigationItems.length - 1;
        this.scrollToFocused();
    };
    MDropdown.prototype.onKeydownUp = function ($event) {
        if (!this.open) {
            return;
        }
        this.focusPreviousItem();
    };
    MDropdown.prototype.onKeydownDown = function ($event) {
        if (!this.open) {
            this.open = true;
        }
        else {
            this.focusNextItem();
        }
    };
    MDropdown.prototype.onKeydownEnter = function ($event) {
        if (!this.open) {
            this.open = true;
        }
        if (this.focusedIndex > -1) {
            var item = this.internalNavigationItems[this.focusedIndex];
            this.model = item.value;
        }
        this.selectText();
    };
    MDropdown.prototype.onKeydownTab = function ($event) {
        if (this.as().isMqMinS) {
            if (this.focusedIndex > -1 && this.internalItems.length === 1) {
                var item = this.internalNavigationItems[this.focusedIndex];
                this.model = item.value;
            }
            this.open = false;
        }
    };
    MDropdown.prototype.onKeydownEsc = function () {
        this.open = false;
    };
    MDropdown.prototype.onInput = function (value) {
        this.$emit('input', value.target.value);
    };
    MDropdown.prototype.focusOnResearchInput = function () {
        this.$refs.researchInput.focus();
    };
    MDropdown.prototype.selectText = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.$nextTick()];
                    case 1:
                        _a.sent();
                        if (!this.isAndroid) {
                            this.$refs.input.focus();
                        }
                        else {
                            this.internalIsFocus = true;
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    MDropdown.prototype.focusSelected = function () {
        var _this = this;
        this.internalNavigationItems.every(function (item, i) {
            if (item.value === _this.model) {
                _this.focusedIndex = i;
                return false;
            }
            else if (_this.filterable && _this.internalFilter !== '' && _this.model === undefined) {
                _this.focusedIndex = 0;
                return false;
            }
            else {
                _this.focusedIndex = -1;
                return true;
            }
        });
        if (this.focusedIndex === -1) {
            this.focusNextItem();
        }
    };
    MDropdown.prototype.focusNextItem = function () {
        if (!this.hasItems) {
            return;
        }
        if (this.focusedIndex > -1) {
            this.focusedIndex++;
            if (this.focusedIndex >= this.internalNavigationItems.length) {
                this.focusedIndex = this.internalNavigationItems.length - 1;
            }
        }
        else {
            this.focusedIndex = this.internalNavigationItems.length === 0 ? -1 : 0;
        }
        this.scrollToFocused();
    };
    MDropdown.prototype.focusPreviousItem = function () {
        if (!this.hasItems) {
            return;
        }
        if (this.focusedIndex > -1) {
            this.focusedIndex--;
            if (this.focusedIndex < 0) {
                this.focusedIndex = 0;
            }
        }
        else {
            this.focusedIndex = this.internalNavigationItems.length - 1;
        }
        this.scrollToFocused();
    };
    MDropdown.prototype.scrollToFocused = function () {
        if (!this.hasItems || this.focusedIndex < 0) {
            return;
        }
        var sidebarBody = this.as().isMqMaxS ?
            document.querySelector("#" + this.popupId + " .m-sidebar__body")
            : undefined;
        var refUl = this.$refs.items;
        var container = sidebarBody || refUl;
        if (container) {
            var element = refUl.children[this.focusedIndex];
            if (element) {
                var top_1 = element.offsetTop;
                var bottom = element.offsetTop + element.offsetHeight;
                var viewRectTop = container.scrollTop;
                var viewRectBottom = viewRectTop + container.clientHeight;
                if (top_1 < viewRectTop) {
                    container.scrollTop = top_1;
                }
                else if (bottom > viewRectBottom) {
                    container.scrollTop = bottom - container.clientHeight;
                }
            }
        }
    };
    MDropdown.prototype.transitionEnter = function (el, done) {
        var _this = this;
        this.$nextTick(function () {
            if (_this.as().isMqMinS) {
                var height_1 = el.clientHeight;
                el.style.transition = DROPDOWN_STYLE_TRANSITION;
                el.style.overflowY = 'hidden';
                el.style.width = _this.$el.clientWidth + 'px';
                if (_this.listMinWidth) {
                    el.style.minWidth = _this.listMinWidth;
                }
                if (_this.enableAnimation) {
                    el.style.maxHeight = '0';
                    requestAnimationFrame(function () {
                        el.style.maxHeight = height_1 + 'px';
                        done();
                    });
                }
                else {
                    done();
                }
            }
            else {
                done();
            }
        });
    };
    MDropdown.prototype.transitionLeave = function (el, done) {
        var _this = this;
        if (this.enableAnimation) {
            if (this.filterable && this.as().isMqMinS) {
                el.style.maxHeight = 'none';
                done();
            }
            else {
                this.$nextTick(function () {
                    var height = el.clientHeight;
                    if (_this.as().isMqMinS) {
                        el.style.maxHeight = height + 'px';
                        el.style.maxHeight = '0';
                        setTimeout(function () {
                            el.style.maxHeight = 'none';
                            done();
                        }, 300);
                    }
                    else {
                        done();
                    }
                });
            }
        }
        else {
            done();
        }
    };
    Object.defineProperty(MDropdown.prototype, "hasPointer", {
        get: function () {
            return !this.as().isDisabled &&
                !this.as().isReadonly &&
                (!this.filterable || (this.filterable && !this.open));
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "hasPlaceholderIcon", {
        get: function () {
            if (UserAgentUtil.isEdge() && !UserAgentUtil.isBlink()) {
                return this.filterable && this.selectedText === '' && !this.as().isReadonly && this.isEdgeSupport;
            }
            else if (UserAgentUtil.isGecko() && !UserAgentUtil.isBlink()) {
                return this.filterable && this.selectedText === '' && !this.as().isReadonly && this.isFirefoxSupport;
            }
            else {
                return this.filterable && this.selectedText === '' && !this.as().isReadonly;
            }
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "isEdgeSupport", {
        get: function () {
            return UserAgentUtil.isEdge() && this.as().placeholder === '' || this.as().placeholder === undefined;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "isFirefoxSupport", {
        get: function () {
            return UserAgentUtil.isGecko() && this.as().placeholder === '' || this.as().placeholder === undefined;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MDropdown.prototype, "isAndroid", {
        get: function () {
            return UserAgentUtil.isAndroid();
        },
        enumerable: false,
        configurable: true
    });
    __decorate([
        Model('change'),
        Prop()
    ], MDropdown.prototype, "value", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "filterable", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "textNoData", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "textNoMatch", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "listMinWidth", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "focus", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "forceOpen", void 0);
    __decorate([
        Prop()
    ], MDropdown.prototype, "maxLength", void 0);
    __decorate([
        Prop({ default: true })
    ], MDropdown.prototype, "showArrowIcon", void 0);
    __decorate([
        Prop({ default: true })
    ], MDropdown.prototype, "enableAnimation", void 0);
    __decorate([
        Prop({ default: true })
    ], MDropdown.prototype, "includeFilterableStatusItems", void 0);
    __decorate([
        Prop({ default: false })
    ], MDropdown.prototype, "clearInvalidSelectionOnClose", void 0);
    __decorate([
        Prop({ default: false })
    ], MDropdown.prototype, "clearModelOnSelectedText", void 0);
    __decorate([
        Prop({ default: function () { return "mDropdown-" + uuid.generate(); } })
    ], MDropdown.prototype, "id", void 0);
    __decorate([
        Prop({ default: uuid.generate() })
    ], MDropdown.prototype, "inputAriaDescribedby", void 0);
    __decorate([
        Watch('forceOpen')
    ], MDropdown.prototype, "onForceOpenUpdate", null);
    __decorate([
        Emit('open')
    ], MDropdown.prototype, "onOpen", null);
    __decorate([
        Emit('close')
    ], MDropdown.prototype, "onClose", null);
    __decorate([
        Watch('value')
    ], MDropdown.prototype, "setInternalValue", null);
    __decorate([
        Watch('focus')
    ], MDropdown.prototype, "focusChanged", null);
    __decorate([
        Watch('isMqMaxS')
    ], MDropdown.prototype, "onIsMqMaxS", null);
    MDropdown = __decorate([
        WithRender,
        Component({
            components: {
                MButton: MButton,
                MInputStyle: MInputStyle,
                MIcon: MIcon,
                MIconButton: MIconButton,
                MValidationMessage: MValidationMessage,
                MPopup: MPopup,
                MDropdownItem: MDropdownItem
            },
            directives: (_a = {},
                _a[DIRECTIVE_POPUP_NAME] = MPopupDirective,
                _a),
            mixins: [
                InputState,
                InputPopup,
                MediaQueries,
                InputManagement,
                InputWidth,
                InputLabel
            ]
        })
    ], MDropdown);
    return MDropdown;
}(BaseDropdown));
export { MDropdown };
var DropdownPlugin = {
    install: function (v, options) {
        Vue.use(MediaQueriesPlugin);
        v.component(DROPDOWN_ITEM_NAME, MDropdownItem);
        v.component(DROPDOWN_NAME, MDropdown);
    }
};
export default DropdownPlugin;
//# sourceMappingURL=dropdown.js.map