import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ElementRef, ViewChild, Renderer2, ViewEncapsulation, ChangeDetectionStrategy, forwardRef, ChangeDetectorRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { coerceBooleanProperty } from '../util/coerce';
import { OnChange } from '../core/decorators';
import { addClass } from '../util/dom';
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var SWITCH_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return SwitchComponent; }),
    multi: true
};
/**
 * Switch Component
 */
var SwitchComponent = /** @class */ (function () {
    function SwitchComponent(_el, _render, _cd) {
        this._el = _el;
        this._render = _render;
        this._cd = _cd;
        /**
         * Event emitted when the switch value changes, emits the checked `boolean` value
         */
        this.change = new EventEmitter();
        /**
         * Whether the switch is checked
         * @default false
         */
        this.checked = false;
        /**
         * Whether the switch is disabled
         * @default false
         */
        this.disabled = false;
        /**
         * Extra theme classes to provide custom themes, when theme is 'small', a `nb-switch-small` class will be added
         * @default ''
         */
        this.theme = '';
        this._dragging = false;
    }
    SwitchComponent.prototype.ngAfterViewInit = function () {
        // add custom theme
        if (this.theme) {
            addClass(this._el.nativeElement, "nb-switch-" + this.theme);
        }
    };
    /**
     * Dispatch change event with current value
     * @docs-private
     */
    SwitchComponent.prototype._onChange = function (event) {
        if (this.disabled) {
            return;
        }
        // We always have to stop propagation on the change event.
        // Otherwise the change event, from the input element, will bubble up and
        // emit its event object to the component's `change` output.
        event.stopPropagation();
        this.checked = this._checkbox.nativeElement.checked;
        this.change.emit(this.checked);
        // update form model
        this.updateFormModel();
    };
    SwitchComponent.prototype._onInputClick = function (event) {
        if (this._dragging) {
            event.preventDefault();
        }
        event.stopPropagation();
    };
    SwitchComponent.prototype._onDragStart = function () {
        if (this.disabled || this._dragging) {
            return;
        }
        this._outerbarWidth = this._outerbar.nativeElement.clientWidth;
        this._innerbarWidth = this._innerbar.nativeElement.clientWidth;
        this._dragging = true;
    };
    SwitchComponent.prototype._onDrag = function (dragEvent) {
        this._updateInnerBarPosition(dragEvent.deltaX);
    };
    SwitchComponent.prototype._onDragEnd = function () {
        var _this = this;
        if (this._dragging) {
            this.checked = this._dragPercentage > 50;
            this.change.emit(this.checked);
            // update form model
            this.updateFormModel();
            setTimeout(function () {
                _this._dragging = false;
                _this._render.setStyle(_this._innerbar.nativeElement, 'transform', '');
                _this._cd.markForCheck();
            });
        }
    };
    SwitchComponent.prototype._updateInnerBarPosition = function (deltaX) {
        this._dragPercentage = this._getDragPercentage(deltaX);
        var dragX = (this._dragPercentage / 100) * (this._outerbarWidth - this._innerbarWidth - 4);
        this._render.setStyle(this._innerbar.nativeElement, 'transform', "translate3d(" + dragX + "px, 0, 0)");
        this._render.setStyle(this._innerbar.nativeElement, 'webkitTransform', "translate3d(" + dragX + "px, 0, 0)");
    };
    SwitchComponent.prototype._getDragPercentage = function (distance) {
        var percentage = (distance / (this._outerbarWidth - this._innerbarWidth - 4)) * 100;
        if (this.checked) {
            percentage += 100;
        }
        return Math.max(0, Math.min(percentage, 100));
    };
    /**
     * Registers a callback that will be triggered when the value has changed.
     * Implemented as part of ControlValueAccessor.
     * @param fn On change callback function.
     */
    SwitchComponent.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.
     */
    SwitchComponent.prototype.registerOnTouched = function (fn) {
        this._onTouch = fn;
    };
    /**
     * Sets the model value. Implemented as part of ControlValueAccessor.
     * @param value Value to be set to the model.
     */
    SwitchComponent.prototype.writeValue = function (value) {
        this.checked = coerceBooleanProperty(value);
        this._cd.markForCheck();
    };
    /**
     * Toggles the disabled state of the component. Implemented as part of ControlValueAccessor.
     * @param isDisabled Whether the component should be disabled.
     */
    SwitchComponent.prototype.setDisabledState = function (isDisabled) {
        this.disabled = isDisabled;
    };
    /**
     * update form model value and mark for check
     * @docs-private
     */
    SwitchComponent.prototype.updateFormModel = function () {
        if (this._onModelChange) {
            this._onModelChange(this.checked);
        }
        if (this._onTouch) {
            this._onTouch(this.checked);
        }
    };
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", EventEmitter)
    ], SwitchComponent.prototype, "change", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], SwitchComponent.prototype, "checked", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], SwitchComponent.prototype, "disabled", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], SwitchComponent.prototype, "theme", void 0);
    tslib_1.__decorate([
        ViewChild('checkbox', { static: false }),
        tslib_1.__metadata("design:type", ElementRef)
    ], SwitchComponent.prototype, "_checkbox", void 0);
    tslib_1.__decorate([
        ViewChild('innerbar', { static: false }),
        tslib_1.__metadata("design:type", ElementRef)
    ], SwitchComponent.prototype, "_innerbar", void 0);
    tslib_1.__decorate([
        ViewChild('outerbar', { static: false }),
        tslib_1.__metadata("design:type", ElementRef)
    ], SwitchComponent.prototype, "_outerbar", void 0);
    SwitchComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-switch',
            template: "<label [class.nb-widget-disabled]=\"disabled\"><div #outerbar class=\"nb-switch-outer\" [class.checked]=\"checked\" [class.nb-switch-outer-dragging]=\"_dragging\"><div #innerbar class=\"nb-switch-inner\" (slidestart)=\"_onDragStart()\" (slide)=\"_onDrag($event)\" (slideend)=\"_onDragEnd()\"></div></div><input #checkbox name=\"chk\" type=\"checkbox\" class=\"visually-hidden\" [checked]=\"checked\" (change)=\"_onChange($event)\" (click)=\"_onInputClick($event)\"> <span class=\"nb-switch-label\"><ng-content></ng-content></span></label>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            providers: [SWITCH_VALUE_ACCESSOR],
            host: {
                'class': 'nb-widget nb-switch'
            },
            exportAs: 'nbSwitch'
        }),
        tslib_1.__metadata("design:paramtypes", [ElementRef, Renderer2, ChangeDetectorRef])
    ], SwitchComponent);
    return SwitchComponent;
}());
export { SwitchComponent };
//# sourceMappingURL=switch.js.map