import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, Renderer2, ViewEncapsulation, ChangeDetectionStrategy, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { OnChange } from '../core/decorators';
import { UP_ARROW, DOWN_ARROW } from '../core/keycodes';
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var SPINNER_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return SpinnerComponent; }),
    multi: true
};
/**
 * Spinner Input Component
 */
var SpinnerComponent = /** @class */ (function () {
    function SpinnerComponent(_cd, _render) {
        this._cd = _cd;
        this._render = _render;
        /**
         * the event emitted when input value changes
         */
        this.change = new EventEmitter();
        /**
         * Spinner value
         * @default 0
         */
        this.value = 0;
        /**
         * Spinner step value, default to 1
         * @default 1
         */
        this.step = 1;
        /**
         * Whether the spinner is disabled
         * @default false
         */
        this.disabled = false;
    }
    /**
     * add a step value
     * @docs-private
     */
    SpinnerComponent.prototype.up = function () {
        if (this.disabled) {
            return;
        }
        // event.preventDefault();
        var nextValue = this.value + this.step;
        var isMaxValue = typeof this.maxValue === 'number' && nextValue > this.maxValue;
        this.value = isMaxValue ? this.maxValue : nextValue;
        this.change.emit(this.value);
        this._markForCheck();
    };
    /**
     * subtract a step value
     * @docs-private
     */
    SpinnerComponent.prototype.down = function () {
        if (this.disabled) {
            return;
        }
        // event.preventDefault();
        var nextValue = this.value - this.step;
        var isMinValue = typeof this.minValue === 'number' && nextValue < this.minValue;
        this.value = isMinValue ? this.minValue : nextValue;
        this.change.emit(this.value);
        this._markForCheck();
    };
    /**
     * check input value
     *
     * @param {string} value - current underlying input value
     * @param {HTMLInputElement} input - underlying input
     * @docs-private
     */
    SpinnerComponent.prototype.onInputCheck = function (value, input) {
        var num = +value;
        if (isNaN(num)) {
            this._render.setProperty(input, 'value', this.value + '');
            return;
        }
        else if (this.hasMaxValue() && num > this.maxValue) {
            this.value = this.maxValue;
            this._render.setProperty(input, 'value', this.value + '');
        }
        else if (this.hasMinValue() && num < this.minValue) {
            this.value = this.minValue;
            this._render.setProperty(input, 'value', this.value + '');
        }
        else {
            this.value = num;
        }
        this.change.emit(this.value);
        this._markForCheck();
    };
    /**
     * Whether the spinner has set max value
     * @docs-private
     */
    SpinnerComponent.prototype.hasMaxValue = function () {
        return typeof this.maxValue === 'number';
    };
    /**
     * Whether the spinner has set min value
     * @docs-private
     */
    SpinnerComponent.prototype.hasMinValue = function () {
        return typeof this.minValue === 'number';
    };
    /**
     * use keyboard up and down arrow
     * @docs-private
     */
    SpinnerComponent.prototype.onInputKeyup = function (keyCode) {
        if (keyCode === UP_ARROW) {
            this.up();
        }
        if (keyCode === DOWN_ARROW) {
            this.down();
        }
    };
    /**
     * Registers a callback that will be triggered when the value has changed.
     * Implemented as part of ControlValueAccessor.
     * @param fn On change callback function.
     */
    SpinnerComponent.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.
     */
    SpinnerComponent.prototype.registerOnTouched = function (fn) {
        this._onTouch = fn;
    };
    /**
     * Sets the model value. Implemented as part of ControlValueAccessor.
     * @param {any} value - value to be set to the model.
     */
    SpinnerComponent.prototype.writeValue = function (value) {
        if (!isNaN(value)) {
            this.value = +value;
            this._cd.markForCheck();
        }
    };
    /**
     * Toggles the disabled state of the component. Implemented as part of ControlValueAccessor.
     * @param {boolean} isDisabled - Whether the component should be disabled.
     */
    SpinnerComponent.prototype.setDisabledState = function (isDisabled) {
        this.disabled = isDisabled;
    };
    /**
     * update form model value and mark for check
     * @docs-private
     */
    SpinnerComponent.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", EventEmitter)
    ], SpinnerComponent.prototype, "change", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Number)
    ], SpinnerComponent.prototype, "value", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Number)
    ], SpinnerComponent.prototype, "step", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Number)
    ], SpinnerComponent.prototype, "minValue", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Number)
    ], SpinnerComponent.prototype, "maxValue", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], SpinnerComponent.prototype, "disabled", void 0);
    SpinnerComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-spinner',
            template: "<input #ipt class=\"nb-spinner-input\" type=\"text\" [value]=\"value\" [disabled]=\"disabled\" (keyup)=\"onInputKeyup($event.keyCode)\" (input)=\"onInputCheck(ipt.value, ipt)\"><div class=\"nb-spinner-button-group\"><button type=\"button\" class=\"nb-spinner-button-up\" (click)=\"up()\"><i class=\"iconfont icon-up\"></i></button> <button type=\"button\" class=\"nb-spinner-button-down\" (click)=\"down()\"><i class=\"iconfont icon-down\"></i></button></div>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            providers: [SPINNER_VALUE_ACCESSOR],
            host: {
                'class': 'nb-widget nb-spinner',
                '[class.nb-spinner-disabled]': 'disabled'
            }
        }),
        tslib_1.__metadata("design:paramtypes", [ChangeDetectorRef, Renderer2])
    ], SpinnerComponent);
    return SpinnerComponent;
}());
export { SpinnerComponent };
//# sourceMappingURL=spinner.js.map