import { CommonModule } from '@angular/common';
import { EventEmitter, ChangeDetectorRef, Optional, Inject, Input, Output, Component, ViewEncapsulation, ChangeDetectionStrategy, ViewChild, InjectionToken, ElementRef, Attribute, Self, NgModule } from '@angular/core';
import { DateAdapter, NT_DATE_FORMATS, fadeOut, fadeIn, NtPseudoInputModule } from '@ng-tangram/components/core';
import { BOTTOM_LEFT, TOP_LEFT, NtOverlayComponent, NtOverlayModule } from '@ng-tangram/components/overlay';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { trigger, transition } from '@angular/animations';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { CdkOverlayOrigin } from '@angular/cdk/overlay';
import { NgControl } from '@angular/forms';
import { NtFormFieldControl } from '@ng-tangram/components/forms';

function createMissingDateImplError(provider) {
    return Error(`NtDatepickerComponent: No provider found for ${provider}. You must import one of the following ` +
        `modules at your application root: NtNativeDateModule or provide a ` +
        `custom implementation.`);
}

class NtDatePickerCell {
    constructor(value, displayValue, enabled) {
        this.value = value;
        this.displayValue = displayValue;
        this.enabled = enabled;
    }
}

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 __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
const DAYS_PER_WEEK = 7;
const DAYS_MAX_ROWS = 6;
let NtDatePickerMonthComponent = class NtDatePickerMonthComponent {
    constructor(_changeDetectorRef, _dateAdapter, _dateFormats) {
        this._changeDetectorRef = _changeDetectorRef;
        this._dateAdapter = _dateAdapter;
        this._dateFormats = _dateFormats;
        this.selectedChange = new EventEmitter();
        this.activeDateChange = new EventEmitter();
        if (!this._dateAdapter) {
            throw createMissingDateImplError('DateAdapter');
        }
        if (!this._dateFormats) {
            throw createMissingDateImplError('NT_DATE_FORMATS');
        }
        const firstDayOfWeek = this._dateAdapter.getFirstDayOfWeek();
        const narrowWeekdays = this._dateAdapter.getDayOfWeekNames('narrow');
        const longWeekdays = this._dateAdapter.getDayOfWeekNames('long');
        let weekdays = longWeekdays.map((long, i) => {
            return { long, narrow: narrowWeekdays[i] };
        });
        this._weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek));
        this._activeDate = this._dateAdapter.today();
    }
    get activeDate() { return this._activeDate; }
    set activeDate(value) {
        const oldActiveDate = this._activeDate;
        const validDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)) || this._dateAdapter.today();
        this._activeDate = this._dateAdapter.clampDate(validDate, this.minDate, this.maxDate);
        if (!this._hasSameMonthAndYear(oldActiveDate, this._activeDate)) {
            this._init();
        }
    }
    get selected() { return this._selected; }
    set selected(value) {
        this._selected = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._selectedDate = this._getDateInCurrentMonth(this._selected);
    }
    get minDate() { return this._minDate; }
    set minDate(value) {
        this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get maxDate() { return this._maxDate; }
    set maxDate(value) {
        this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    ngAfterContentInit() {
        this._init();
    }
    _dateSelected(cell) {
        if (cell.enabled && this._selectedDate !== cell.value) {
            const selectedYear = this._dateAdapter.getYear(this.activeDate);
            const selectedMonth = this._dateAdapter.getMonth(this.activeDate);
            const selectedDate = this._dateAdapter.createDate(selectedYear, selectedMonth, cell.value);
            this.selectedChange.emit(selectedDate);
        }
    }
    _init() {
        this._selectedDate = this._getDateInCurrentMonth(this.selected);
        this._todayDate = this._getDateInCurrentMonth(this._dateAdapter.today());
        this._monthLabel = this._dateAdapter.getMonthNames('short')[this._dateAdapter.getMonth(this.activeDate)]
            .toLocaleUpperCase();
        const firstOfMonth = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), 1);
        this._firstWeekOffset = (DAYS_PER_WEEK + this._dateAdapter.getDayOfWeek(firstOfMonth) -
            this._dateAdapter.getFirstDayOfWeek()) % DAYS_PER_WEEK;
        this._createWeekCells();
        this._changeDetectorRef.markForCheck();
    }
    _createWeekCells() {
        const daysInMonth = this._dateAdapter.getNumDaysInMonth(this.activeDate);
        const dateNames = this._dateAdapter.getDateNames();
        this._weeks = [[]];
        for (let i = 0, cell = this._firstWeekOffset; i < daysInMonth; i++, cell++) {
            if (cell === DAYS_PER_WEEK) {
                this._weeks.push([]);
                cell = 0;
            }
            const date = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), i + 1);
            const enabled = this._shouldEnableDate(date);
            this._weeks[this._weeks.length - 1].push(new NtDatePickerCell(i + 1, dateNames[i], enabled));
        }
        this._fillBeforeCells();
        this._fillAfterCells();
    }
    _getWeekOffset() {
        const firstDayForCurrentMonth = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), 1);
        const firstDayForWeek = this._dateAdapter.getDayOfWeek(firstDayForCurrentMonth);
        return firstDayForWeek - this._dateAdapter.getFirstDayOfWeek() >= 0
            ? firstDayForWeek - this._dateAdapter.getFirstDayOfWeek()
            : firstDayForWeek - this._dateAdapter.getFirstDayOfWeek() + DAYS_PER_WEEK;
    }
    _fillBeforeCells() {
        const beforeMonth = this._dateAdapter.addCalendarMonths(this._dateAdapter.clone(this.activeDate), -1);
        const daysInBeforeMonth = this._dateAdapter.getNumDaysInMonth(beforeMonth);
        const dateNames = this._dateAdapter.getDateNames();
        const beforeWeeks = [];
        for (let i = daysInBeforeMonth - this._firstWeekOffset; i < daysInBeforeMonth; i++) {
            beforeWeeks.push(new NtDatePickerCell(i + 1, dateNames[i], false));
        }
        this._weeks[0] = beforeWeeks.concat(this._weeks[0]);
    }
    _fillAfterCells() {
        const afterMonth = this._dateAdapter.addCalendarMonths(this._dateAdapter.clone(this.activeDate), 1);
        const lastRow = this._weeks[this._weeks.length - 1];
        const dateNames = this._dateAdapter.getDateNames();
        const afterWeeks = [], afterRows = [];
        for (let i = 0; i < DAYS_PER_WEEK - lastRow.length; i++) {
            afterWeeks.push(new NtDatePickerCell(i + 1, dateNames[i], false));
        }
        lastRow.push(...afterWeeks);
        for (let i = 0; i < DAYS_PER_WEEK * (DAYS_MAX_ROWS - this._weeks.length); i++) {
            afterRows.push(new NtDatePickerCell(afterWeeks.length + i + 1, dateNames[afterWeeks.length + i], false));
        }
        this._weeks.push(...afterRows.map(_ => afterRows.splice(0, DAYS_PER_WEEK)).filter(row => !!row));
    }
    _shouldEnableDate(date) {
        return !!date &&
            (!this.dateFilter || this.dateFilter(date)) &&
            (!this.minDate || this._dateAdapter.compareDate(date, this.minDate) >= 0) &&
            (!this.maxDate || this._dateAdapter.compareDate(date, this.maxDate) <= 0);
    }
    _getDateInCurrentMonth(date) {
        return date && this._hasSameMonthAndYear(date, this.activeDate) ?
            this._dateAdapter.getDate(date) : null;
    }
    _hasSameMonthAndYear(d1, d2) {
        return !!(d1 && d2 && this._dateAdapter.getMonth(d1) === this._dateAdapter.getMonth(d2) &&
            this._dateAdapter.getYear(d1) === this._dateAdapter.getYear(d2));
    }
    _getValidDateOrNull(obj) {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }
};
NtDatePickerMonthComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: DateAdapter, decorators: [{ type: Optional }] },
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NT_DATE_FORMATS,] }] }
];
__decorate([
    Input()
], NtDatePickerMonthComponent.prototype, "activeDate", null);
__decorate([
    Input()
], NtDatePickerMonthComponent.prototype, "selected", null);
__decorate([
    Input()
], NtDatePickerMonthComponent.prototype, "minDate", null);
__decorate([
    Input()
], NtDatePickerMonthComponent.prototype, "maxDate", null);
__decorate([
    Input()
], NtDatePickerMonthComponent.prototype, "dateFilter", void 0);
__decorate([
    Output()
], NtDatePickerMonthComponent.prototype, "selectedChange", void 0);
__decorate([
    Output()
], NtDatePickerMonthComponent.prototype, "activeDateChange", void 0);
NtDatePickerMonthComponent = __decorate([
    Component({
        selector: 'nt-datepicker-month',
        template: "<table>\n  <thead>\n    <tr>\n      <th *ngFor=\"let week of _weekdays\">{{week.narrow}}</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr *ngFor=\"let _rows of _weeks\">\n      <td *ngFor=\"let week of _rows\"\n        [class.disabled]=\"!week.enabled\"\n        [class.selected]=\"week.value === _selectedDate && week.enabled\"\n        [class.active]=\"_todayDate === week.value && week.enabled\">\n        <span (click)=\"_dateSelected(week)\">{{ week.displayValue }}</span>\n      </td>\n    </tr>\n  </tbody>\n</table>\n<!-- <button class=\"button tiny expanded clear margin-bottom-0\" [disabled]=\"_isTodaySelected()\" (click)=\"_todaySelected()\">\u4ECA\u65E5</button> -->\n",
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        host: {
            'class': 'nt-datepicker-month'
        }
    }),
    __param(1, Optional()),
    __param(2, Optional()), __param(2, Inject(NT_DATE_FORMATS))
], NtDatePickerMonthComponent);

var __decorate$1 = (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 __param$1 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
const yearsPerPage = 12;
const yearsPerRow = 3;
let NtDatePickerMultiYearComponent = class NtDatePickerMultiYearComponent {
    constructor(_changeDetectorRef, _dateAdapter) {
        this._changeDetectorRef = _changeDetectorRef;
        this._dateAdapter = _dateAdapter;
        this.selectedChange = new EventEmitter();
        this.yearSelected = new EventEmitter();
        if (!this._dateAdapter) {
            throw createMissingDateImplError('DateAdapter');
        }
        this._activeDate = this._dateAdapter.today();
    }
    get activeDate() { return this._activeDate; }
    set activeDate(value) {
        let oldActiveDate = this._activeDate;
        const validDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)) || this._dateAdapter.today();
        this._activeDate = this._dateAdapter.clampDate(validDate, this.minDate, this.maxDate);
        if (Math.floor(this._dateAdapter.getYear(oldActiveDate) / yearsPerPage) !==
            Math.floor(this._dateAdapter.getYear(this._activeDate) / yearsPerPage)) {
            this._init();
        }
    }
    get selected() { return this._selected; }
    set selected(value) {
        this._selected = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._selectedYear = this._selected && this._dateAdapter.getYear(this._selected);
    }
    get minDate() { return this._minDate; }
    set minDate(value) {
        this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get maxDate() { return this._maxDate; }
    set maxDate(value) {
        this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    ngAfterContentInit() {
        this._init();
    }
    _init() {
        this._todayYear = this._dateAdapter.getYear(this._dateAdapter.today());
        let activeYear = this._dateAdapter.getYear(this._activeDate);
        let activeOffset = activeYear % yearsPerPage;
        this._years = [];
        for (let i = 0, row = []; i < yearsPerPage; i++) {
            row.push(activeYear - activeOffset + i);
            if (row.length === yearsPerRow) {
                this._years.push(row.map(year => this._createCellForYear(year)));
                row = [];
            }
        }
        this._changeDetectorRef.markForCheck();
    }
    _yearSelected(year) {
        this.yearSelected.emit(this._dateAdapter.createDate(year, 0, 1));
        let month = this._dateAdapter.getMonth(this.activeDate);
        let daysInMonth = this._dateAdapter.getNumDaysInMonth(this._dateAdapter.createDate(year, month, 1));
        this.selectedChange.emit(this._dateAdapter.createDate(year, month, Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth)));
    }
    _createCellForYear(year) {
        let yearName = this._dateAdapter.getYearName(this._dateAdapter.createDate(year, 0, 1));
        return new NtDatePickerCell(year, yearName, this._shouldEnableYear(year));
    }
    _shouldEnableYear(year) {
        if (year === undefined || year === null ||
            (this.maxDate && year > this._dateAdapter.getYear(this.maxDate)) ||
            (this.minDate && year < this._dateAdapter.getYear(this.minDate))) {
            return false;
        }
        if (!this.dateFilter) {
            return true;
        }
        const firstOfYear = this._dateAdapter.createDate(year, 0, 1);
        for (let date = firstOfYear; this._dateAdapter.getYear(date) === year; date = this._dateAdapter.addCalendarDays(date, 1)) {
            if (this.dateFilter(date)) {
                return true;
            }
        }
        return false;
    }
    _getValidDateOrNull(obj) {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }
};
NtDatePickerMultiYearComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: DateAdapter, decorators: [{ type: Optional }] }
];
__decorate$1([
    Input()
], NtDatePickerMultiYearComponent.prototype, "activeDate", null);
__decorate$1([
    Input()
], NtDatePickerMultiYearComponent.prototype, "selected", null);
__decorate$1([
    Input()
], NtDatePickerMultiYearComponent.prototype, "minDate", null);
__decorate$1([
    Input()
], NtDatePickerMultiYearComponent.prototype, "maxDate", null);
__decorate$1([
    Input()
], NtDatePickerMultiYearComponent.prototype, "dateFilter", void 0);
__decorate$1([
    Output()
], NtDatePickerMultiYearComponent.prototype, "selectedChange", void 0);
__decorate$1([
    Output()
], NtDatePickerMultiYearComponent.prototype, "yearSelected", void 0);
NtDatePickerMultiYearComponent = __decorate$1([
    Component({
        selector: 'nt-datepicker-multi-year',
        template: "<table>\n  <tbody>\n    <tr *ngFor=\"let _rows of _years\">\n      <td *ngFor=\"let year of _rows\"\n        [class.disabled]=\"!year.enabled\"\n        [class.selected]=\"year.value === _selectedYear && year.enabled\"\n        (click)=\"_yearSelected(year.value)\">\n        <span *ngIf=\"year.enabled\">{{ year.displayValue }}</span>\n        <span *ngIf=\"!year.enabled\">{{ year.displayValue }}</span>\n      </td>\n    </tr>\n  </tbody>\n</table>\n",
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        host: {
            'class': 'nt-datepicker-multi-year'
        }
    }),
    __param$1(1, Optional())
], NtDatePickerMultiYearComponent);

var __decorate$2 = (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 __param$2 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtDatePickerYearComponent = class NtDatePickerYearComponent {
    constructor(_changeDetectorRef, _dateAdapter, _dateFormats) {
        this._changeDetectorRef = _changeDetectorRef;
        this._dateAdapter = _dateAdapter;
        this._dateFormats = _dateFormats;
        this.selectedChange = new EventEmitter();
        this.monthSelected = new EventEmitter();
        if (!this._dateAdapter) {
            throw createMissingDateImplError('DateAdapter');
        }
        if (!this._dateFormats) {
            throw createMissingDateImplError('NT_DATE_FORMATS');
        }
        this._activeDate = this._dateAdapter.today();
    }
    get activeDate() { return this._activeDate; }
    set activeDate(value) {
        let oldActiveDate = this._activeDate;
        const validDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)) || this._dateAdapter.today();
        this._activeDate = this._dateAdapter.clampDate(validDate, this.minDate, this.maxDate);
        if (this._dateAdapter.getYear(oldActiveDate) !== this._dateAdapter.getYear(this._activeDate)) {
            this._init();
        }
    }
    get activeYear() { return this._activeDate ? this._dateAdapter.getYear(this._activeDate) : null; }
    get selected() { return this._selected; }
    set selected(value) {
        this._selected = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._selectedMonth = this._getMonthInCurrentYear(this._selected);
    }
    get minDate() { return this._minDate; }
    set minDate(value) {
        this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get maxDate() { return this._maxDate; }
    set maxDate(value) {
        this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    ngAfterContentInit() {
        this._init();
    }
    _init() {
        this._selectedMonth = this._getMonthInCurrentYear(this.selected);
        this._todayMonth = this._getMonthInCurrentYear(this._dateAdapter.today());
        const monthNames = this._dateAdapter.getMonthNames('short');
        this._months = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]].map(row => row.map(month => this._createCellForMonth(month, monthNames[month])));
        this._changeDetectorRef.markForCheck();
    }
    _monthSelected(month) {
        const normalizedDate = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), month, 1);
        this.monthSelected.emit(normalizedDate);
        const daysInMonth = this._dateAdapter.getNumDaysInMonth(normalizedDate);
        this.selectedChange.emit(this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), month, Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth)));
    }
    _createCellForMonth(month, monthName) {
        return new NtDatePickerCell(month, monthName.toLocaleUpperCase(), this._shouldEnableMonth(month));
    }
    _shouldEnableMonth(month) {
        const activeYear = this._dateAdapter.getYear(this.activeDate);
        if (month === undefined || month === null ||
            this._isYearAndMonthAfterMaxDate(activeYear, month) ||
            this._isYearAndMonthBeforeMinDate(activeYear, month)) {
            return false;
        }
        if (!this.dateFilter) {
            return true;
        }
        const firstOfMonth = this._dateAdapter.createDate(activeYear, month, 1);
        for (let date = firstOfMonth; this._dateAdapter.getMonth(date) === month; date = this._dateAdapter.addCalendarDays(date, 1)) {
            if (this.dateFilter(date)) {
                return true;
            }
        }
        return false;
    }
    _isYearAndMonthAfterMaxDate(year, month) {
        if (this.maxDate) {
            const maxYear = this._dateAdapter.getYear(this.maxDate);
            const maxMonth = this._dateAdapter.getMonth(this.maxDate);
            return year > maxYear || (year === maxYear && month > maxMonth);
        }
        return false;
    }
    _isYearAndMonthBeforeMinDate(year, month) {
        if (this.minDate) {
            const minYear = this._dateAdapter.getYear(this.minDate);
            const minMonth = this._dateAdapter.getMonth(this.minDate);
            return year < minYear || (year === minYear && month < minMonth);
        }
        return false;
    }
    _getMonthInCurrentYear(date) {
        return date && this._dateAdapter.getYear(date) === this._dateAdapter.getYear(this.activeDate) ?
            this._dateAdapter.getMonth(date) : null;
    }
    _getValidDateOrNull(obj) {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }
};
NtDatePickerYearComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: DateAdapter, decorators: [{ type: Optional }] },
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NT_DATE_FORMATS,] }] }
];
__decorate$2([
    Input()
], NtDatePickerYearComponent.prototype, "activeDate", null);
__decorate$2([
    Input()
], NtDatePickerYearComponent.prototype, "selected", null);
__decorate$2([
    Input()
], NtDatePickerYearComponent.prototype, "minDate", null);
__decorate$2([
    Input()
], NtDatePickerYearComponent.prototype, "maxDate", null);
__decorate$2([
    Input()
], NtDatePickerYearComponent.prototype, "dateFilter", void 0);
__decorate$2([
    Output()
], NtDatePickerYearComponent.prototype, "selectedChange", void 0);
__decorate$2([
    Output()
], NtDatePickerYearComponent.prototype, "monthSelected", void 0);
NtDatePickerYearComponent = __decorate$2([
    Component({
        selector: 'nt-datepicker-year',
        template: "<table>\n  <tbody>\n    <tr *ngFor=\"let _rows of _months\">\n      <td *ngFor=\"let month of _rows\"\n        [class.disabled]=\"!month.enabled\"\n        [class.selected]=\"month.value === _selectedMonth && month.enabled\"\n        (click)=\"_monthSelected(month.value)\">\n        <span *ngIf=\"month.enabled\">{{ month.displayValue }}</span>\n        <span *ngIf=\"!month.enabled\">{{ month.displayValue }}</span>\n      </td>\n    </tr>\n  </tbody>\n</table>\n",
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        host: {
            'class': 'nt-datepicker-year'
        }
    }),
    __param$2(1, Optional()),
    __param$2(2, Optional()), __param$2(2, Inject(NT_DATE_FORMATS))
], NtDatePickerYearComponent);

var __decorate$3 = (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 __param$3 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtDatePickerCalendarComponent = class NtDatePickerCalendarComponent {
    constructor(_changeDetectorRef, _dateAdapter, _dateFormats) {
        this._changeDetectorRef = _changeDetectorRef;
        this._dateAdapter = _dateAdapter;
        this._dateFormats = _dateFormats;
        this._viewType = 'month';
        this._currentView = 'month';
        this.selectedChange = new EventEmitter();
        this.yearSelected = new EventEmitter();
        this.monthSelected = new EventEmitter();
        if (!this._dateAdapter) {
            throw createMissingDateImplError('DateAdapter');
        }
        if (!this._dateFormats) {
            throw createMissingDateImplError('NT_DATE_FORMATS');
        }
    }
    get startAt() { return this._startAt; }
    set startAt(value) {
        this._startAt = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get selected() { return this._selected; }
    set selected(value) {
        this._selected = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get minDate() { return this._minDate; }
    set minDate(value) {
        this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get maxDate() { return this._maxDate; }
    set maxDate(value) {
        this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
    }
    get _activeDate() { return this._clampedActiveDate; }
    set _activeDate(value) {
        this._clampedActiveDate = this._dateAdapter.clampDate(value, this.minDate, this.maxDate);
    }
    get _monthLabel() {
        return this._dateAdapter.format(this._activeDate, this._dateFormats.display.monthLabel).toLocaleUpperCase();
    }
    get _yearLabel() { return this._dateAdapter.getYearName(this._activeDate); }
    get _multiYearLabel() {
        const activeYear = this._dateAdapter.getYear(this._activeDate);
        const firstYearInView = this._dateAdapter.getYearName(this._dateAdapter.createDate(activeYear - activeYear % yearsPerPage, 0, 1), 'en-US');
        const lastYearInView = this._dateAdapter.getYearName(this._dateAdapter.createDate(activeYear + yearsPerPage - 1 - activeYear % yearsPerPage, 0, 1), 'en-US');
        return `${firstYearInView} \u2013 ${lastYearInView}`;
    }
    ngAfterContentInit() {
        this._init();
    }
    ngOnChanges(changes) {
        const change = changes.minDate || changes.maxDate || changes.dateFilter;
        if (change && !change.firstChange) {
            const view = this.monthView || this.yearView || this.multiYearView;
            if (view) {
                view._init();
            }
        }
    }
    ngOnDestroy() {
    }
    prevMonth() {
        this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, -1);
    }
    nextMonth() {
        this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, 1);
    }
    prevYear() {
        this._activeDate = this._dateAdapter.addCalendarYears(this._activeDate, -1);
    }
    nextYear() {
        this._activeDate = this._dateAdapter.addCalendarYears(this._activeDate, 1);
    }
    prevYearArray() {
        this._activeDate = this._dateAdapter.addCalendarYears(this._activeDate, -yearsPerPage);
    }
    nextYearArray() {
        this._activeDate = this._dateAdapter.addCalendarYears(this._activeDate, yearsPerPage);
    }
    _init() {
        this._activeDate = this.startAt || this._dateAdapter.today();
        this._currentView = this._viewType;
        this._changeDetectorRef.markForCheck();
    }
    _dateSelected(date) {
        if (!this._dateAdapter.sameDate(date, this.selected)) {
            this.selectedChange.emit(date);
        }
    }
    _yearSelectedInMultiYearView(normalizedYear) {
        this.yearSelected.emit(normalizedYear);
    }
    _monthSelectedInYearView(normalizedMonth) {
        this.monthSelected.emit(normalizedMonth);
    }
    _goToDateInView(date, view) {
        this._activeDate = date;
        this._currentView = view;
    }
    _getValidDateOrNull(obj) {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }
};
NtDatePickerCalendarComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: DateAdapter, decorators: [{ type: Optional }] },
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NT_DATE_FORMATS,] }] }
];
__decorate$3([
    Input()
], NtDatePickerCalendarComponent.prototype, "startAt", null);
__decorate$3([
    Input()
], NtDatePickerCalendarComponent.prototype, "selected", null);
__decorate$3([
    Input()
], NtDatePickerCalendarComponent.prototype, "minDate", null);
__decorate$3([
    Input()
], NtDatePickerCalendarComponent.prototype, "maxDate", null);
__decorate$3([
    Input()
], NtDatePickerCalendarComponent.prototype, "dateFilter", void 0);
__decorate$3([
    Output()
], NtDatePickerCalendarComponent.prototype, "selectedChange", void 0);
__decorate$3([
    Output()
], NtDatePickerCalendarComponent.prototype, "yearSelected", void 0);
__decorate$3([
    Output()
], NtDatePickerCalendarComponent.prototype, "monthSelected", void 0);
__decorate$3([
    ViewChild(NtDatePickerMonthComponent)
], NtDatePickerCalendarComponent.prototype, "monthView", void 0);
__decorate$3([
    ViewChild(NtDatePickerYearComponent)
], NtDatePickerCalendarComponent.prototype, "yearView", void 0);
__decorate$3([
    ViewChild(NtDatePickerMultiYearComponent)
], NtDatePickerCalendarComponent.prototype, "multiYearView", void 0);
NtDatePickerCalendarComponent = __decorate$3([
    Component({
        selector: 'nt-datepicker-calendar',
        template: "<div class=\"nt-datepicker-pane\" [ngSwitch]=\"_currentView\">\n  <table>\n    <thead>\n      <tr *ngSwitchCase=\"'month'\"><ng-container *ngTemplateOutlet=\"monthControl\"></ng-container></tr>\n      <tr *ngSwitchCase=\"'year'\"><ng-container *ngTemplateOutlet=\"yearControl\"></ng-container></tr>\n      <tr *ngSwitchCase=\"'multi-year'\"><ng-container *ngTemplateOutlet=\"multiYearControl\"></ng-container></tr>\n    </thead>\n  </table>\n  <nt-datepicker-month\n    *ngSwitchCase=\"'month'\"\n    [(activeDate)]=\"_activeDate\"\n    [selected]=\"selected\"\n    [dateFilter]=\"dateFilter\"\n    [maxDate]=\"maxDate\"\n    [minDate]=\"minDate\"\n    (selectedChange)=\"_dateSelected($event)\">\n  </nt-datepicker-month>\n  <nt-datepicker-year\n    *ngSwitchCase=\"'year'\"\n    [activeDate]=\"_activeDate\"\n    [selected]=\"selected\"\n    [dateFilter]=\"dateFilter\"\n    [maxDate]=\"maxDate\"\n    [minDate]=\"minDate\"\n    (monthSelected)=\"_monthSelectedInYearView($event)\"\n    (selectedChange)=\"_goToDateInView($event, 'month')\">\n  </nt-datepicker-year>\n  <nt-datepicker-multi-year\n    *ngSwitchCase=\"'multi-year'\"\n    [activeDate]=\"_activeDate\"\n    [selected]=\"selected\"\n    [dateFilter]=\"dateFilter\"\n    [maxDate]=\"maxDate\"\n    [minDate]=\"minDate\"\n    (yearSelected)=\"_yearSelectedInMultiYearView($event)\"\n    (selectedChange)=\"_goToDateInView($event, 'year')\">\n  </nt-datepicker-multi-year>\n</div>\n\n<ng-template #monthControl>\n  <th (click)=\"prevYear()\" [class.disabled]=\"\"><span>&laquo;</span></th>\n  <th (click)=\"prevMonth()\" [class.disabled]=\"\"><span>&lsaquo;</span></th>\n  <th colspan=\"3\">\n    <span (click)=\" _currentView = 'multi-year' \">{{ _yearLabel }}</span>\n    <span (click)=\" _currentView = 'year' \">{{ _monthLabel }}</span>\n  </th>\n  <th (click)=\"nextMonth()\" [class.disabled]=\"\"><span>&rsaquo;</span></th>\n  <th (click)=\"nextYear()\" [class.disabled]=\"\"><span>&raquo;</span></th>\n</ng-template>\n<ng-template #yearControl>\n  <th (click)=\"prevYear()\" [class.disabled]=\"\"><span>&laquo;</span></th>\n  <th>&nbsp;</th>\n  <th colspan=\"3\">\n    <span (click)=\" _currentView = 'multi-year' \">{{ _yearLabel }}</span>\n  </th>\n  <th>&nbsp;</th>\n  <th (click)=\"nextYear()\" [class.disabled]=\"\"><span>&raquo;</span></th>\n</ng-template>\n<ng-template #multiYearControl>\n  <th (click)=\"prevYearArray()\"><span>&laquo;</span></th>\n  <th>&nbsp;</th>\n  <th colspan=\"3\">{{_multiYearLabel}}</th>\n  <th>&nbsp;</th>\n  <th (click)=\"nextYearArray()\"><span>&raquo;</span></th>\n</ng-template>\n",
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush
    }),
    __param$3(1, Optional()),
    __param$3(2, Optional()), __param$3(2, Inject(NT_DATE_FORMATS))
], NtDatePickerCalendarComponent);

const DEFAULT_DATEPICKER_ICONS = {
    caret: 'far fa-calendar-alt',
    clear: 'fa fa-times'
};
const NT_DATEPICKER_ICONS = new InjectionToken('nt-datepicker-icons');

var __decorate$4 = (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 __param$4 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var NtDatePickerComponent_1;
let NtDatePickerComponent = NtDatePickerComponent_1 = class NtDatePickerComponent extends NtFormFieldControl {
    constructor(_elementRef, _dateAdapter, _dateFormats, tabIndex, ngControl, icons) {
        super();
        this._elementRef = _elementRef;
        this._dateAdapter = _dateAdapter;
        this._dateFormats = _dateFormats;
        this.ngControl = ngControl;
        this.icons = icons;
        this._overlayToggle = new Subject();
        this._positionPairs = [BOTTOM_LEFT, TOP_LEFT];
        this._displayValue = '';
        this._placeholder = '';
        this._disabled = false;
        this._required = false;
        this._readonly = false;
        this.afterOpen = new EventEmitter();
        this.afterClosed = new EventEmitter();
        this.beforeOpen = new EventEmitter();
        this.beforeClosed = new EventEmitter();
        this.positionChange = new EventEmitter();
        this._onChange = () => { };
        this._onTouched = () => { };
        this.origin = new CdkOverlayOrigin(_elementRef);
        if (this.ngControl) {
            this.ngControl.valueAccessor = this;
        }
        this.icons = Object.assign(Object.assign({}, DEFAULT_DATEPICKER_ICONS), icons);
        this.tabIndex = parseInt(tabIndex) || 0;
        this._overlayToggle.pipe(debounceTime(10)).subscribe(open => open
            ? this.overlay.open()
            : this.overlay.toggle());
    }
    get empty() { return !this.value; }
    get value() { return this._value; }
    set value(value) {
        value = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._value = value;
        this._displayValue = value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '';
    }
    set placeholder(value) { this._placeholder = value; }
    get placeholder() { return this._placeholder; }
    set disabled(value) { this._disabled = coerceBooleanProperty(value); }
    get disabled() { return this._disabled; }
    get required() { return this._required; }
    set required(value) { this._required = coerceBooleanProperty(value); }
    set readonly(value) { this._readonly = coerceBooleanProperty(value); }
    get readonly() { return this._readonly; }
    get startAt() { return this._startAt || this.value; }
    set startAt(value) { this._startAt = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); }
    get minDate() { return this._minDate; }
    set minDate(value) { this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); }
    get maxDate() { return this._maxDate; }
    set maxDate(value) { this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); }
    writeValue(value) {
        this.value = value;
    }
    registerOnChange(fn) {
        this._onChange = fn;
    }
    registerOnTouched(fn) {
        this._onTouched = fn;
    }
    select(date) {
        this.value = date;
        this.overlay.close();
        this._onChange(date);
    }
    focus() {
        this.overlay.open();
    }
    _onAfterOpen(event) {
        this.afterOpen.next(event);
    }
    _onAfterClosed(event) {
        this.afterClosed.next(event);
    }
    _onBeforeOpen(event) {
        this.calendar._init();
        this.beforeOpen.next(event);
    }
    _onBeforeClosed(event) {
        typeof this._onTouched === 'function' && this._onTouched();
        this.beforeClosed.next(event);
    }
    _onPositionChange(change) {
        this.positionChange.next(change);
    }
    _onClick(event) {
        if (!this.disabled) {
            this.overlay.toggle();
        }
        event.stopPropagation();
    }
    _onClear(event) {
        if (this.value !== null && !this.disabled) {
            this.value = null;
            this._onChange(this.value);
        }
        event.stopPropagation();
    }
    setDisabledState(isDisabled) {
        this._disabled = isDisabled;
    }
    _getValidDateOrNull(obj) {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }
};
NtDatePickerComponent.ctorParameters = () => [
    { type: ElementRef },
    { type: DateAdapter },
    { type: undefined, decorators: [{ type: Inject, args: [NT_DATE_FORMATS,] }] },
    { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] },
    { type: NgControl, decorators: [{ type: Optional }, { type: Self }] },
    { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NT_DATEPICKER_ICONS,] }] }
];
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "placeholder", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "disabled", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "required", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "readonly", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "startAt", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "minDate", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "maxDate", null);
__decorate$4([
    Input()
], NtDatePickerComponent.prototype, "dateFilter", void 0);
__decorate$4([
    Output()
], NtDatePickerComponent.prototype, "afterOpen", void 0);
__decorate$4([
    Output()
], NtDatePickerComponent.prototype, "afterClosed", void 0);
__decorate$4([
    Output()
], NtDatePickerComponent.prototype, "beforeOpen", void 0);
__decorate$4([
    Output()
], NtDatePickerComponent.prototype, "beforeClosed", void 0);
__decorate$4([
    Output()
], NtDatePickerComponent.prototype, "positionChange", void 0);
__decorate$4([
    ViewChild(NtOverlayComponent, { static: true })
], NtDatePickerComponent.prototype, "overlay", void 0);
__decorate$4([
    ViewChild(NtDatePickerCalendarComponent, { static: true })
], NtDatePickerComponent.prototype, "calendar", void 0);
NtDatePickerComponent = NtDatePickerComponent_1 = __decorate$4([
    Component({
        selector: 'nt-datepicker',
        template: "\n<nt-pseudo-input\n  [style.margin.px]=\"0\"\n  [attr.tabindex]=\"tabIndex\"\n  [value]=\"_displayValue\"\n  [placeholder]=\"placeholder\"\n  [disabled]=\"disabled\">\n  <nt-pseudo-caret *ngIf=\"!value || disabled\">\n    <span [class]=\"icons.caret\"></span>\n  </nt-pseudo-caret>\n  <nt-pseudo-caret class=\"nt-datepicker-clear\" (click)=\"_onClear($event)\" *ngIf=\"value && !disabled\">\n    <span [class]=\"icons.clear\"></span>\n  </nt-pseudo-caret>\n</nt-pseudo-input>\n\n<nt-overlay\n  overlayClass=\"nt-datepicker-overlay\"\n  [origin]=\"origin\"\n  [positionPairs]=\"_positionPairs\"\n  arrow\n  (afterOpen)=\"_onAfterOpen($event)\"\n  (afterClosed)=\"_onAfterClosed($event)\"\n  (beforeOpen)=\"_onBeforeOpen($event)\"\n  (beforeClosed)=\"_onBeforeClosed($event)\"\n  (positionChange)=\"_onPositionChange($event)\">\n  <nt-datepicker-calendar\n    [selected]=\"value\"\n    [dateFilter]=\"dateFilter\"\n    [startAt]=\"startAt\"\n    [maxDate]=\"maxDate\"\n    [minDate]=\"minDate\"\n    (selectedChange)=\"select($event)\">\n  </nt-datepicker-calendar>\n</nt-overlay>\n",
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'nt-datepicker',
            '(click)': '_onClick($event)',
        },
        animations: [
            trigger('fade', [
                transition('* => void', fadeOut(.15)),
                transition('void => *', fadeIn(.15))
            ])
        ],
        providers: [
            { provide: NtFormFieldControl, useExisting: NtDatePickerComponent_1 }
        ]
    }),
    __param$4(2, Inject(NT_DATE_FORMATS)),
    __param$4(3, Attribute('tabindex')),
    __param$4(4, Optional()), __param$4(4, Self()),
    __param$4(5, Optional()), __param$4(5, Inject(NT_DATEPICKER_ICONS))
], NtDatePickerComponent);

var __decorate$5 = (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;
};
let NtDatePickerModule = class NtDatePickerModule {
};
NtDatePickerModule = __decorate$5([
    NgModule({
        imports: [
            CommonModule,
            NtOverlayModule,
            NtPseudoInputModule,
        ],
        exports: [NtDatePickerComponent],
        declarations: [
            NtDatePickerComponent,
            NtDatePickerCalendarComponent,
            NtDatePickerMonthComponent,
            NtDatePickerYearComponent,
            NtDatePickerMultiYearComponent
        ]
    })
], NtDatePickerModule);

export { DEFAULT_DATEPICKER_ICONS, NT_DATEPICKER_ICONS, NtDatePickerCalendarComponent, NtDatePickerCell, NtDatePickerComponent, NtDatePickerModule, NtDatePickerMonthComponent, NtDatePickerMultiYearComponent, NtDatePickerYearComponent, createMissingDateImplError, yearsPerPage, yearsPerRow };
//# sourceMappingURL=datepicker.js.map
