/**
 * xdesign
 *
 * @file date range picker
 * @author csu.zengxiaohui@gmail.com
 */
import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, Renderer2, ViewChild, ElementRef, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { format, subDays, setDate, lastDayOfMonth, subWeeks, lastDayOfWeek, setDay } from 'date-fns';
import { OverlayComponent } from '../overlay';
import { OverlayOriginDirective } from '../overlay/overlay-origin.directive';
import { OnChange } from '../core/decorators';
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var RANGEDATEPICKER_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return RangeDatePickerComponent; }),
    multi: true
};
/**
 * Range DatePicker Component
 */
var RangeDatePickerComponent = /** @class */ (function () {
    function RangeDatePickerComponent(render, cd, el) {
        this.render = render;
        this.cd = cd;
        this.el = el;
        /** range datepicker change event, emit a `RangeDatePickerValue` value */
        this.change = new EventEmitter();
        this._value = {
            startDate: new Date(),
            endDate: new Date()
        };
        /** the splitter symbol between two dates show in input text */
        this.splitter = '~';
        /** the format date show */
        this.formatter = 'yyyy-MM-dd';
        /** the quick links array */
        this.quickLinks = [
            {
                text: '昨天',
                startDate: subDays(new Date(), 1),
                endDate: subDays(new Date(), 1)
            },
            {
                text: '今天',
                startDate: new Date(),
                endDate: new Date()
            },
            {
                // not include today
                text: '最近7天',
                startDate: subDays(new Date(), 7),
                endDate: subDays(new Date(), 1)
            },
            {
                text: '上周',
                startDate: setDay(subWeeks(new Date(), 1), 1, { weekStartsOn: 1 }),
                endDate: lastDayOfWeek(subWeeks(new Date(), 1), { weekStartsOn: 1 })
            },
            {
                text: '本月',
                startDate: setDate(new Date(), 1),
                endDate: lastDayOfMonth(new Date())
            }
        ];
        /** whether the range datepicker is disabled */
        this.disabled = false;
        /** whether the panel is show */
        this._showPanel = false;
    }
    Object.defineProperty(RangeDatePickerComponent.prototype, "value", {
        /** range datepicker value */
        get: function () { return this._value; },
        set: function (newValue) {
            if (newValue) {
                this._value = newValue;
                this._startDate = newValue.startDate;
                this._endDate = newValue.endDate;
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RangeDatePickerComponent.prototype, "valueText", {
        /**
         * get the text show in input box
         * @readonly
         * @docs-private
         */
        get: function () {
            return [
                format(this.value.startDate, this.formatter),
                ' ' + this.splitter + ' ',
                format(this.value.endDate, this.formatter)
            ].join('');
        },
        enumerable: true,
        configurable: true
    });
    RangeDatePickerComponent.prototype.ngOnInit = function () {
        this.overlay.origin = this.origin;
    };
    RangeDatePickerComponent.prototype.ngOnDestroy = function () {
    };
    RangeDatePickerComponent.prototype.onShowCalendar = function () {
        if (this._showPanel) {
            this._hideOverlay();
        }
        else {
            if (!this.disabled) {
                this._showOverlay();
            }
        }
    };
    RangeDatePickerComponent.prototype._hideOverlay = function () {
        this.overlay.hide();
        this._showPanel = false;
    };
    RangeDatePickerComponent.prototype._showOverlay = function () {
        this.overlay.show();
        this._showPanel = true;
    };
    RangeDatePickerComponent.prototype.onFilterPanelHide = function (_panel) {
        this._showPanel = false;
    };
    RangeDatePickerComponent.prototype.onSelectStartDate = function (date) {
        this.value.startDate = date;
        this.setStartAndEndDate(date);
    };
    RangeDatePickerComponent.prototype.onSelectEndDate = function (date) {
        this.value.endDate = date;
        this.setStartAndEndDate(date);
    };
    /**
     * set range datepicker start and end date range
     * @param {Date} date - currently selected date
     * @docs-private
     */
    RangeDatePickerComponent.prototype.setStartAndEndDate = function (date) {
        // if all have set, reset start date and set end date to null
        if (this._startDate && this._endDate) {
            this._startDate = date;
            this._endDate = null;
            return;
        }
        // if no start date, set this date as a start date
        if (!this._startDate) {
            this._startDate = date;
            return;
        }
        // if no end date(already has a start date), set this date as a end date
        if (!this._endDate) {
            this._endDate = date;
            // make sure that start date is smaller than end date, if not, exchange
            var max = Math.max(+this._startDate, +this._endDate);
            var min = Math.min(+this._startDate, +this._endDate);
            this.value.startDate = new Date(min);
            this.value.endDate = new Date(max);
        }
    };
    /**
     * quickly set date range
     * @param {QuickLinkValue} quickLink - quick link item
     * @docs-private
     */
    RangeDatePickerComponent.prototype.onClickQuickLink = function (quickLink) {
        if (this.disabled) {
            return;
        }
        this.quickLinks.forEach(function (v) { return v.selected = false; });
        quickLink.selected = true;
        // set selection range
        this._startDate = quickLink.startDate;
        this._endDate = quickLink.endDate;
        // set value
        this.value.startDate = quickLink.startDate;
        this.value.endDate = quickLink.endDate;
    };
    /**
     * confirm range value
     * @docs-private
     */
    RangeDatePickerComponent.prototype.onConfirm = function () {
        this._exchangeValueIfNesscery(this.value);
        this.change.emit(this.value);
        // reset highlight range start
        this._startDate = this.value.startDate;
        this._endDate = this.value.endDate;
        this._hideOverlay();
        this._markForCheck();
    };
    /**
     * make sure startDate is less than endDate
     * @param value
     */
    RangeDatePickerComponent.prototype._exchangeValueIfNesscery = function (value) {
        var startDate = +value.startDate;
        var endDate = +value.endDate;
        var max = Math.max(startDate, endDate);
        var min = Math.min(startDate, endDate);
        this.value.startDate = new Date(min);
        this.value.endDate = new Date(max);
    };
    /**
     * hide panel
     * @docs-private
     */
    RangeDatePickerComponent.prototype.onCancel = function () {
        this._hideOverlay();
    };
    /**
     * Registers a callback that will be triggered when the value has changed.
     * Implemented as part of ControlValueAccessor.
     * @param fn On change callback function.
     */
    RangeDatePickerComponent.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.
     */
    RangeDatePickerComponent.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.
     */
    RangeDatePickerComponent.prototype.writeValue = function (value) {
        if (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.
     */
    RangeDatePickerComponent.prototype.setDisabledState = function (isDisabled) {
        this.disabled = isDisabled;
    };
    /**
     * update form model value and mark for check
     * @docs-private
     */
    RangeDatePickerComponent.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)
    ], RangeDatePickerComponent.prototype, "change", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Object),
        tslib_1.__metadata("design:paramtypes", [Object])
    ], RangeDatePickerComponent.prototype, "value", null);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], RangeDatePickerComponent.prototype, "splitter", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], RangeDatePickerComponent.prototype, "formatter", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Array)
    ], RangeDatePickerComponent.prototype, "quickLinks", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], RangeDatePickerComponent.prototype, "disabled", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Function)
    ], RangeDatePickerComponent.prototype, "disabledStrategy", void 0);
    tslib_1.__decorate([
        ViewChild('origin', { static: true }),
        tslib_1.__metadata("design:type", OverlayOriginDirective)
    ], RangeDatePickerComponent.prototype, "origin", void 0);
    tslib_1.__decorate([
        ViewChild('overlay', { static: true }),
        tslib_1.__metadata("design:type", OverlayComponent)
    ], RangeDatePickerComponent.prototype, "overlay", void 0);
    RangeDatePickerComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-range-datepicker',
            template: "<div class=\"nb-rangedatepicker-input-area\" (click)=\"onShowCalendar()\"><input nbOverlayOrigin #origin=\"nbOverlayOrigin\" readonly=\"readonly\" type=\"text\" class=\"nb-rangedatepicker-input\" [ngModel]=\"valueText\" [disabled]=\"disabled\"></div><nb-overlay #overlay placement=\"bottom-left\" (closeHandler)=\"onFilterPanelHide($event)\"><div class=\"nb-rangedatepicker-calendar-panel\"><div class=\"nb-rangedatepicker-quicklinks\" *ngIf=\"quickLinks && quickLinks.length\"><div *ngFor=\"let quicklink of quickLinks\" class=\"nb-rangedatepicker-quicklink\" [class.nb-rangedatepicker-quicklink-selected]=\"quicklink.selected\" (click)=\"onClickQuickLink(quicklink)\">{{ quicklink.text }}</div></div><div class=\"nb-rangedatepicker-calendars\"><nb-calendar [value]=\"value.startDate\" [startDate]=\"_startDate\" [endDate]=\"_endDate\" [disabled]=\"disabled\" [disabledStrategy]=\"disabledStrategy\" (select)=\"onSelectStartDate($event)\"></nb-calendar><nb-calendar [value]=\"value.endDate\" [startDate]=\"_startDate\" [endDate]=\"_endDate\" [disabled]=\"disabled\" [disabledStrategy]=\"disabledStrategy\" (select)=\"onSelectEndDate($event)\"></nb-calendar></div><div class=\"nb-rangedatepicker-buttons\"><button (click)=\"onConfirm()\" nb-button theme=\"primary\" size=\"xs\" type=\"button\">确定</button> <button (click)=\"onCancel()\" nb-button theme=\"default\" size=\"xs\" type=\"button\">取消</button></div></div></nb-overlay>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            providers: [RANGEDATEPICKER_VALUE_ACCESSOR],
            preserveWhitespaces: false,
            host: {
                'class': 'nb-widget nb-rangedatepicker',
                '[class.disabled]': 'disabled'
            },
            exportAs: 'nbRangeDatePicker'
        }),
        tslib_1.__metadata("design:paramtypes", [Renderer2, ChangeDetectorRef, ElementRef])
    ], RangeDatePickerComponent);
    return RangeDatePickerComponent;
}());
export { RangeDatePickerComponent };
//# sourceMappingURL=range-datepicker.js.map