import * as tslib_1 from "tslib";
import { Component, ChangeDetectorRef, Input, Output, EventEmitter, forwardRef, ViewEncapsulation, ViewChild, ChangeDetectionStrategy, ElementRef, NgZone } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subscription, fromEvent, merge } from 'rxjs';
import { auditTime, delay } from 'rxjs/operators';
/** Time in ms to throttle the resize|scroll events by default. */
export var DEFAULT_DELAY_TIME = 100;
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var SEARCHBOX_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return SearchBoxComponent; }),
    multi: true
};
var SearchBoxComponent = /** @class */ (function () {
    function SearchBoxComponent(_cd, el, ngZone) {
        this._cd = _cd;
        this.el = el;
        this.ngZone = ngZone;
        /** search event */
        this.onSearch = new EventEmitter();
        /** clear search event */
        this.onClear = new EventEmitter();
        /** suggest search event */
        this.onSearchSuggestion = new EventEmitter();
        /**
         * search-box type: either 'ico' or 'btn'
         * @default 'ico'
         */
        this.type = 'ico';
        /**
         * search-box size, there three default size: 'long' | 'default' | 'short'
         * @default 'default'
         */
        this.size = 'default';
        /**
         * Whether the search-box is suggest search: either true or false
         * @default 'false'
         */
        this.isSuggestion = false;
        /**
         * search-box default placeholder
         * @default '按关键词搜索'
         */
        this.placeholder = '按关键词搜索';
        /**
         * Whether the search-box is disabled
         * @default false
         */
        this.disabled = false;
        /**
         * search-box mode,default 'keyup',have two mode: 'keyup','focus'.
         * @default 'keyup'
         */
        this.mode = 'keyup';
        /**
         * search-box value
         * @default ''
         */
        this.value = '';
        /**
         * search-box suggest search value
         * @default []
         */
        this.suggestionValue = [];
        /**
         * init suggest search region is not open
         * @docs-private
         */
        this.isOpen = false;
        /**
         * Subscription to viewport resize|scroll events.
         * @docs-private
         */
        this._resizeSubscription = Subscription.EMPTY;
        /**
         * composing value, default false
         * @docs-private
         */
        this._composing = false;
        /**
         * input in search-box default size
         * @docs-private
         */
        this._sizeIpt = 'default';
        /**
         * buttion in search-box default size
         * @docs-private
         */
        this._sizeBtn = 'default';
        /**
         * 计时器
         * @docs-private
         */
        this._timer = Subscription.EMPTY;
        this._change = ngZone.runOutsideAngular(function () {
            return merge(fromEvent(window, 'resize'), fromEvent(window, 'scroll'));
        });
    }
    SearchBoxComponent.prototype.ngOnInit = function () {
        var _this = this;
        var self = this;
        if (this.isSuggestion !== false) {
            // window resize or scroll
            this._resizeSubscription = this.change().subscribe(function () { return _this.positionSuggestionLayer(_this); });
            // // suggestionLayer close timeout
            var searchIpt = this.searchInput.nativeElement;
            this._inputBlur = fromEvent(searchIpt, 'blur');
            this._timer = this.blurInput().subscribe(function () { return _this.closeSuggestionLayer(_this); });
        }
        switch (this.size) {
            case 'small':
                this._sizeIpt = 'short-middle';
                this._sizeBtn = 'sm';
                break;
            case 'long':
                this._sizeIpt = 'long-high';
                this._sizeBtn = 'lg';
                break;
            default:
                this._sizeIpt = 'default';
                this._sizeBtn = 'default';
        }
        this.setClass();
    };
    SearchBoxComponent.prototype.ngOnDestroy = function () {
        this._resizeSubscription.unsubscribe();
        this._timer.unsubscribe();
    };
    /**
     * set search-box class
     * @docs-private
     */
    SearchBoxComponent.prototype.setClass = function () {
        var nativeEl = this.el.nativeElement;
        nativeEl.className = this.getClassName(nativeEl.className);
    };
    /**
     * get search-box class
     * @param className
     * @docs-private
     */
    SearchBoxComponent.prototype.getClassName = function (className) {
        return className + ' ' + ("nb-search-box-size-" + (this.size || 'default'));
    };
    /**
     * return a stream that emits whenever the input blur event happen
     * @param throttleTime
     * @docs-private
     */
    SearchBoxComponent.prototype.blurInput = function (throttleTime) {
        if (throttleTime === void 0) { throttleTime = DEFAULT_DELAY_TIME; }
        return throttleTime > 0 ? this._inputBlur.pipe(delay(throttleTime)) : this._inputBlur;
    };
    /**
     * close suggestion layer
     * @param self
     * @docs-private
     */
    SearchBoxComponent.prototype.closeSuggestionLayer = function (self) {
        self.isOpen = false;
        self._cd.markForCheck();
    };
    /**
     * Returns a stream that emits whenever the size of the viewport change|scroll.
     * @param throttle Time in milliseconds to throttle the stream.
     * @docs-private
     */
    SearchBoxComponent.prototype.change = function (throttleTime) {
        if (throttleTime === void 0) { throttleTime = DEFAULT_DELAY_TIME; }
        return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change;
    };
    /**
     * position suggestion layer
     * @docs-private
     */
    SearchBoxComponent.prototype.positionSuggestionLayer = function (self) {
        var elLayer = self.el.nativeElement.getElementsByClassName('nb-search-box-suggestion-layer');
        if (elLayer.length) {
            /**
             * 156 = 36 + 110 + 10
             * @docs-private
             */
            var pos = window.scrollY + window.innerHeight - self.el.nativeElement.offsetTop - 156 > 0
                ? 'bottom' : 'top';
            elLayer[0].className += ' nb-search-box-suggestion-layer-' + pos;
        }
    };
    /**
     * 处理compositionstart事件
     * @docs-private
     */
    SearchBoxComponent.prototype._compositionStart = function () {
        this._composing = true;
    };
    /**
     * 处理compositionend事件
     * @docs-private
     */
    SearchBoxComponent.prototype._compositionEnd = function () {
        this._composing = false;
    };
    /**
     * listen keyword input in search-box
     * @param event
     * @docs-private
     */
    SearchBoxComponent.prototype.onInputValue = function (event) {
        if (this.isSuggestion !== false && event.keyCode !== 13 && this.value && !this._composing) {
            this.fnSugguestValue();
        }
        if (!this.value) {
            this.isOpen = false;
        }
    };
    /**
     * listen enter keydown event in search-box
     * @param event
     * @docs-private
     */
    SearchBoxComponent.prototype.onKeydown = function (event) {
        if (event.keyCode === 13) {
            // 阻止input回车时的默认事件，以免search-box应用在表单时响应回车事件提交表单
            event.preventDefault();
            this.isOpen = false;
            this.onSearch.emit(this.value);
            this._cd.markForCheck();
        }
        if (event.keyCode === 8 && this.value.length === 1) {
            event.preventDefault();
            this.value = '';
            this.searchInput.nativeElement.placeholder = this.placeholder;
            this.onSearch.emit(this.value);
            this._cd.markForCheck();
        }
    };
    /**
     * realize search-box suggest function
     * @docs-private
     */
    SearchBoxComponent.prototype.fnSugguestValue = function () {
        this.positionSuggestionLayer(this);
        this.onSearchSuggestion.emit(this.value);
        this.isOpen = true;
        this._cd.markForCheck();
    };
    /**
     * clear keyword in search-box
     * @param ipt
     * @docs-private
     */
    SearchBoxComponent.prototype.clearSearch = function (ipt) {
        this.value = '';
        ipt.placeholder = this.placeholder;
        this.onClear.emit(this.value);
        this._cd.markForCheck();
    };
    /**
     * search use keyword event
     * @docs-private
     */
    SearchBoxComponent.prototype.search = function () {
        this.onSearch.emit(this.value);
        this._markForCheck();
    };
    /**
     * click select suggest search value
     * @docs-private
     */
    SearchBoxComponent.prototype.selectSuggestionValue = function (suggestionItem) {
        this.value = suggestionItem;
        this.onSearch.emit(this.value);
        this._cd.markForCheck();
        this._markForCheck();
    };
    /**
     * listen focus on input event
     * @param ipt
     * @docs-private
     */
    SearchBoxComponent.prototype.onFocus = function (ipt) {
        ipt.placeholder = '';
        if (this.mode === 'focus') {
            this.fnSugguestValue();
        }
    };
    /**
     * listen blur input event
     * @param ipt
     * @docs-private
     */
    SearchBoxComponent.prototype.onBlur = function (ipt) {
        var self = this;
        if (!ipt.value) {
            ipt.placeholder = this.placeholder;
        }
    };
    /**
     * Registers a callback that will be triggered when the value has changed.
     * Implemented as part of ControlValueAccessor.
     * @param fn On change callback function.
     */
    SearchBoxComponent.prototype.registerOnChange = function (fn) {
        this._onModelChange = fn;
    };
    /**
     * Registers a callback that will be triggered when the control has been touched.
     * Implemented as part of ControlValueAccessor.
     * @param fn On touch callback function.
     */
    SearchBoxComponent.prototype.registerOnTouched = function (fn) {
        this._onTouch = fn;
    };
    /**
     * set search-box model value
     * @docs-private
     */
    SearchBoxComponent.prototype.writeValue = function (value) {
        this.value = value;
        this._cd.markForCheck();
    };
    /**
     * update form model value and mark for check
     * @docs-private
     */
    SearchBoxComponent.prototype._markForCheck = function () {
        if (this._onModelChange) {
            this._onModelChange(this.value);
        }
        if (this._onTouch) {
            this._onTouch(this.value);
        }
        this._cd.markForCheck();
    };
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", Object)
    ], SearchBoxComponent.prototype, "onSearch", void 0);
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", Object)
    ], SearchBoxComponent.prototype, "onClear", void 0);
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", Object)
    ], SearchBoxComponent.prototype, "onSearchSuggestion", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SearchBoxComponent.prototype, "type", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SearchBoxComponent.prototype, "size", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], SearchBoxComponent.prototype, "isSuggestion", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SearchBoxComponent.prototype, "placeholder", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], SearchBoxComponent.prototype, "disabled", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SearchBoxComponent.prototype, "mode", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SearchBoxComponent.prototype, "value", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Array)
    ], SearchBoxComponent.prototype, "suggestionValue", void 0);
    tslib_1.__decorate([
        ViewChild('searchInput', { static: true }),
        tslib_1.__metadata("design:type", ElementRef)
    ], SearchBoxComponent.prototype, "searchInput", void 0);
    SearchBoxComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-search-box',
            template: "<input nbInput theme=\"default\" #searchInput type=\"text\" class=\"nb-search-box-input\" [size]=\"_sizeIpt\" [placeholder]=\"placeholder\" [disabled]=\"disabled\" [(ngModel)]=\"value\" (focus)=\"onFocus(searchInput)\" (blur)=\"onBlur(searchInput)\" (keyup)=\"onInputValue($event)\" (keydown)=\"onKeydown($event)\"><div class=\"nb-search-box-operate\"><div class=\"nb-search-box-icons\"><button *ngIf=\"value.length > 0\" nb-button type=\"button\" theme=\"transparent\" class=\"nb-clear\" (click)=\"clearSearch(searchInput)\" [size]=\"_sizeBtn\" [disabled]=\"disabled\"><i class=\"iconfont icon-close\"></i></button> <button *ngIf=\"type==='ico'\" nb-button type=\"button\" theme=\"transparent\" class=\"nb-search\" (click)=\"search()\" [size]=\"_sizeBtn\" [disabled]=\"disabled\"><i class=\"iconfont icon-search\"></i></button> <button *ngIf=\"type==='btn'\" nb-button type=\"button\" theme=\"primary\" (click)=\"search()\" [size]=\"_sizeBtn\" [disabled]=\"disabled\">搜索</button></div></div><div *ngIf=\"isOpen\" class=\"nb-search-box-suggestion-layer\" [class.nb-search-box-suggest-empty]=\"suggestionValue.length === 0\"><ul class=\"nb-search-box-suggestion-list\"><li *ngFor=\"let item of suggestionValue\" class=\"nb-search-box-suggestion-item\" (click)=\"selectSuggestionValue(item)\">{{ item }}</li></ul></div>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            providers: [SEARCHBOX_VALUE_ACCESSOR],
            host: {
                'class': 'nb-widget nb-search-box',
                '[class.nb-search-box-disabled]': 'disabled',
                '[class.nb-search-box-ico]': 'type == "ico"',
                '[class.nb-search-box-btn]': 'type == "btn"',
                '(compositionstart)': '_compositionStart()',
                '(compositionend)': '_compositionEnd()'
            }
        }),
        tslib_1.__metadata("design:paramtypes", [ChangeDetectorRef,
            ElementRef,
            NgZone])
    ], SearchBoxComponent);
    return SearchBoxComponent;
}());
export { SearchBoxComponent };
//# sourceMappingURL=search-box.js.map