/* eslint-disable @typescript-eslint/naming-convention */
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 __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
// #region Imports
import { HTMLElementEventEmitter } from '@breadstone/mosaik-elements';
import { Emit } from '../../Events/Decorators/EmitDecorator';
import { AutoCompleteController } from '../Controllers/AutoCompleteController';
import { Attribute } from '../Decorators/AttributeDecorator';
import { Property } from '../Decorators/PropertyDecorator';
import { AutoCompleteTextSearchMode } from '../Types/AutoCompleteTextSearchMode';
/**
 * @public
 */
export const AutoCompleteable = (base) => {
    class AutoCompleteableElement extends base {
        // #region Fields
        _autoCompleteController;
        _populating;
        _populated;
        _minimumPrefixLength;
        _minimumPopulateDelay;
        _isTextCompletionEnabled;
        _searchMode;
        _displayMemberPath;
        _items;
        _filteredItems;
        // #endregion
        // #region Ctor
        /**
         * Constructs a new instance of the `AutoCompleteable` class.
         *
         * @public
         */
        constructor(...args) {
            super(args);
            this._minimumPrefixLength = 1;
            this._minimumPopulateDelay = 500;
            this._isTextCompletionEnabled = false;
            this._searchMode = AutoCompleteTextSearchMode.Contains;
            this._displayMemberPath = '';
            this._items = [];
            this._filteredItems = [];
            this._populating = new HTMLElementEventEmitter(this, 'populating');
            this._populated = new HTMLElementEventEmitter(this, 'populated');
            this._autoCompleteController = new AutoCompleteController(this, {
                filterCallback: (x) => {
                    this.onFilterCallback(x);
                },
                selectCallback: (x) => {
                    this.onSelectCallback(x);
                }
            });
        }
        // #endregion
        // #region Properties
        /**
         * Gets or sets the `minimumPrefixLength` property.
         * The default value is `1`, which means the search will start after typing one character.
         *
         * @public
         * @attr
         */
        get minimumPrefixLength() {
            return this._minimumPrefixLength;
        }
        set minimumPrefixLength(value) {
            if (this._minimumPrefixLength !== value) {
                this._minimumPrefixLength = value;
                this.requestUpdate('minimumPrefixLength');
            }
        }
        /**
         * Gets or sets the `minimumPopulateDelay` property.
         * The default value is `500`, which means the search will be delayed by 500 milliseconds after the last keystroke.
         *
         * @public
         * @attr
         */
        get minimumPopulateDelay() {
            return this._minimumPopulateDelay;
        }
        set minimumPopulateDelay(value) {
            if (this._minimumPopulateDelay !== value) {
                this._minimumPopulateDelay = value;
                this.requestUpdate('minimumPopulateDelay');
            }
        }
        /**
         * Gets or sets the `isTextCompletionEnabled` property.
         * The default value is `false`, which means text completion is disabled.
         *
         * @public
         * @attr
         */
        get isTextCompletionEnabled() {
            return this._isTextCompletionEnabled;
        }
        set isTextCompletionEnabled(value) {
            if (this._isTextCompletionEnabled !== value) {
                this._isTextCompletionEnabled = value;
                this.requestUpdate('isTextCompletionEnabled');
            }
        }
        /**
         * Gets or sets the `searchMode` property.
         * The default value is `contains`, which means the search will match any part of the text.
         *
         * @public
         * @attr
         */
        get searchMode() {
            return this._searchMode;
        }
        set searchMode(value) {
            if (this._searchMode !== value) {
                this._searchMode = value;
                this.requestUpdate('searchMode');
            }
        }
        /**
         * Gets or sets the `displayMemberPath` property.
         * The default value is an empty string, which means the item itself will be used for display.
         *
         * @public
         * @attr
         */
        get displayMemberPath() {
            return this._displayMemberPath;
        }
        set displayMemberPath(value) {
            if (this._displayMemberPath !== value) {
                this._displayMemberPath = value;
                this.requestUpdate('displayMemberPath');
            }
        }
        /**
         * Gets or sets the `items` property.
         * The default value is an empty array, which means no items are available.
         *
         * @public
         */
        get items() {
            return this._items;
        }
        set items(value) {
            if (this._items !== value) {
                this._items = value;
                this.requestUpdate('items');
            }
        }
        /**
         * Gets or sets the `filteredItems` property.
         * The default value is an empty array, which means no items are filtered.
         *
         * @public
         * @readonly
         */
        get filteredItems() {
            return this._filteredItems;
        }
        set filteredItems(value) {
            if (this._filteredItems !== value) {
                this._filteredItems = value;
                this.requestUpdate('filteredItems');
            }
        }
        /**
         * Called when the items are being populated.
         * Provides reference to `{@link IEventDetail}` as event detail.
         *
         * @public
         * @readonly
         * @eventProperty
         */
        get populating() {
            return this._populating;
        }
        /**
         * Called when the items have been populated.
         * Provides reference to `{@link IEventDetail}` as event detail.
         *
         * @public
         * @readonly
         * @eventProperty
         */
        get populated() {
            return this._populated;
        }
        // #endregion
        // #region Methods
        /**
         * @public
         * @virtual
         */
        onFilterCallback(items) {
            this.filteredItems = items;
        }
        /**
         * @public
         * @virtual
         */
        onSelectCallback(_item) {
            // Override
        }
        /**
         * @public
         */
        updateSearchText(searchText) {
            this._autoCompleteController.updateSearchText(this.items, searchText, this.minimumPrefixLength, this.searchMode, this.displayMemberPath);
        }
        /**
         * @public
         */
        updateSelectedItem(item) {
            this._autoCompleteController.selectItem(item);
        }
        /**
         * @public
         */
        getDisplayValue(item) {
            return this._autoCompleteController.getDisplayValue(item, this.displayMemberPath);
        }
        /**
         * Emits the {@link populating} event.
         *
         * @protected
         */
        onPopulating(args) {
            this._populating.emit(args);
        }
        /**
         * Emits the {@link populated} event.
         *
         * @protected
         */
        onPopulated(args) {
            this._populated.emit(args);
        }
    }
    __decorate([
        Attribute({ type: Number }),
        __metadata("design:type", Number),
        __metadata("design:paramtypes", [Number])
    ], AutoCompleteableElement.prototype, "minimumPrefixLength", null);
    __decorate([
        Attribute({ type: Number }),
        __metadata("design:type", Number),
        __metadata("design:paramtypes", [Number])
    ], AutoCompleteableElement.prototype, "minimumPopulateDelay", null);
    __decorate([
        Attribute({ type: Boolean }),
        __metadata("design:type", Boolean),
        __metadata("design:paramtypes", [Boolean])
    ], AutoCompleteableElement.prototype, "isTextCompletionEnabled", null);
    __decorate([
        Attribute({ type: String }),
        __metadata("design:type", String),
        __metadata("design:paramtypes", [String])
    ], AutoCompleteableElement.prototype, "searchMode", null);
    __decorate([
        Attribute({ type: String }),
        __metadata("design:type", String),
        __metadata("design:paramtypes", [String])
    ], AutoCompleteableElement.prototype, "displayMemberPath", null);
    __decorate([
        Property({ type: Array }),
        __metadata("design:type", Array),
        __metadata("design:paramtypes", [Array])
    ], AutoCompleteableElement.prototype, "items", null);
    __decorate([
        Property({ type: Array }),
        __metadata("design:type", Array),
        __metadata("design:paramtypes", [Array])
    ], AutoCompleteableElement.prototype, "filteredItems", null);
    __decorate([
        Emit({ eventName: 'populating' }),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [])
    ], AutoCompleteableElement.prototype, "populating", null);
    __decorate([
        Emit({ eventName: 'populated' }),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [])
    ], AutoCompleteableElement.prototype, "populated", null);
    return AutoCompleteableElement;
};
//# sourceMappingURL=AutoCompleteable.js.map