define(["require", "exports", "tslib", "react", "../../Utilities", "../../utilities/dateValues/DateValues", "../../FocusZone", "../../Icon", "../../utilities/dateMath/DateMath", "./Calendar.scss"], function (require, exports, tslib_1, React, Utilities_1, DateValues_1, FocusZone_1, Icon_1, DateMath_1, stylesImport) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var styles = stylesImport;
    var DAYS_IN_WEEK = 7;
    var CalendarDay = /** @class */ (function (_super) {
        tslib_1.__extends(CalendarDay, _super);
        function CalendarDay(props) {
            var _this = _super.call(this, props) || this;
            _this.state = {
                activeDescendantId: Utilities_1.getId('DatePickerDay-active'),
                weeks: _this._getWeeks(props)
            };
            _this._onSelectNextMonth = _this._onSelectNextMonth.bind(_this);
            _this._onSelectPrevMonth = _this._onSelectPrevMonth.bind(_this);
            return _this;
        }
        CalendarDay.prototype.componentWillReceiveProps = function (nextProps) {
            this.setState({
                weeks: this._getWeeks(nextProps)
            });
        };
        CalendarDay.prototype.render = function () {
            var _this = this;
            var _a = this.state, activeDescendantId = _a.activeDescendantId, weeks = _a.weeks;
            var _b = this.props, firstDayOfWeek = _b.firstDayOfWeek, strings = _b.strings, navigatedDate = _b.navigatedDate, selectedDate = _b.selectedDate, dateRangeType = _b.dateRangeType, navigationIcons = _b.navigationIcons, showWeekNumbers = _b.showWeekNumbers, firstWeekOfYear = _b.firstWeekOfYear, dateTimeFormatter = _b.dateTimeFormatter, minDate = _b.minDate, maxDate = _b.maxDate;
            var dayPickerId = Utilities_1.getId('DatePickerDay-dayPicker');
            var monthAndYearId = Utilities_1.getId('DatePickerDay-monthAndYear');
            var leftNavigationIcon = navigationIcons.leftNavigation;
            var rightNavigationIcon = navigationIcons.rightNavigation;
            var weekNumbers = showWeekNumbers ? DateMath_1.getWeekNumbersInMonth(weeks.length, firstDayOfWeek, firstWeekOfYear, navigatedDate) : null;
            var selectedDateWeekNumber = showWeekNumbers ? DateMath_1.getWeekNumber(selectedDate, firstDayOfWeek, firstWeekOfYear) : undefined;
            // When the month is highlighted get the corner dates so that styles can be added to them
            var weekCorners = {};
            if (dateRangeType === DateValues_1.DateRangeType.Month && selectedDate.getMonth() === navigatedDate.getMonth() && selectedDate.getFullYear() === navigatedDate.getFullYear()) {
                // navigatedDate is on the current month and current year
                weekCorners = this._getWeekCornerStyles(weeks);
            }
            // determine if previous/next months are in bounds
            var prevMonthInBounds = minDate ? DateMath_1.compareDatePart(minDate, DateMath_1.getMonthStart(navigatedDate)) < 0 : true;
            var nextMonthInBounds = maxDate ? DateMath_1.compareDatePart(DateMath_1.getMonthEnd(navigatedDate), maxDate) < 0 : true;
            return (React.createElement("div", { className: Utilities_1.css('ms-DatePicker-dayPicker', styles.dayPicker, showWeekNumbers && 'ms-DatePicker-showWeekNumbers' && (Utilities_1.getRTL() ? styles.showWeekNumbersRTL : styles.showWeekNumbers)), id: dayPickerId },
                React.createElement("div", { className: Utilities_1.css('ms-DatePicker-monthComponents', styles.monthComponents) },
                    React.createElement("div", { className: Utilities_1.css('ms-DatePicker-navContainer', styles.navContainer) },
                        React.createElement("button", { className: Utilities_1.css('ms-DatePicker-prevMonth js-prevMonth', styles.prevMonth, (_c = {},
                                _c['ms-DatePicker-prevMonth--disabled ' + styles.prevMonthIsDisabled] = !prevMonthInBounds,
                                _c)), onClick: this._onSelectPrevMonth, onKeyDown: this._onPrevMonthKeyDown, "aria-controls": dayPickerId, "aria-label": strings.prevMonthAriaLabel ? strings.prevMonthAriaLabel + ' ' + strings.months[DateMath_1.addMonths(navigatedDate, -1).getMonth()] : undefined, role: 'button', tabIndex: 0 },
                            React.createElement(Icon_1.Icon, { iconName: leftNavigationIcon })),
                        React.createElement("button", { className: Utilities_1.css('ms-DatePicker-nextMonth js-nextMonth', styles.nextMonth, (_d = {},
                                _d['ms-DatePicker-nextMonth--disabled ' + styles.nextMonthIsDisabled] = !nextMonthInBounds,
                                _d)), onClick: this._onSelectNextMonth, onKeyDown: this._onNextMonthKeyDown, "aria-controls": dayPickerId, "aria-label": strings.nextMonthAriaLabel ? strings.nextMonthAriaLabel + ' ' + strings.months[DateMath_1.addMonths(navigatedDate, 1).getMonth()] : undefined, role: 'button', tabIndex: 0 },
                            React.createElement(Icon_1.Icon, { iconName: rightNavigationIcon })))),
                React.createElement("div", { className: Utilities_1.css('ms-DatePicker-header', styles.header) },
                    React.createElement("div", { "aria-live": 'polite', "aria-relevant": 'text', "aria-atomic": 'true', id: monthAndYearId }, this.props.onHeaderSelect ?
                        React.createElement("div", { className: Utilities_1.css('ms-DatePicker-monthAndYear js-showMonthPicker', styles.monthAndYear, styles.headerToggleView), onClick: this._onHeaderSelect, onKeyDown: this._onHeaderKeyDown, "aria-label": dateTimeFormatter.formatMonthYear(navigatedDate, strings), role: 'button', tabIndex: 0 }, dateTimeFormatter.formatMonthYear(navigatedDate, strings))
                        :
                            React.createElement("div", { className: Utilities_1.css('ms-DatePicker-monthAndYear', styles.monthAndYear) }, dateTimeFormatter.formatMonthYear(navigatedDate, strings)))),
                React.createElement(FocusZone_1.FocusZone, null,
                    showWeekNumbers ?
                        React.createElement("table", { className: Utilities_1.css('ms-DatePicker-weekNumbers', styles.weekNumbers, 'ms-DatePicker-table', styles.table) },
                            React.createElement("tbody", null, weekNumbers.map(function (weekNumber, index) {
                                return React.createElement("tr", { key: index },
                                    React.createElement("td", null,
                                        React.createElement("div", { className: Utilities_1.css('ms-DatePicker-day', styles.day, (_a = {},
                                                _a['ms-DatePicker-week--highlighted ' + styles.weekIsHighlighted] = selectedDateWeekNumber === weekNumber,
                                                _a)) },
                                            React.createElement("span", null, weekNumber))));
                                var _a;
                            })))
                        : null,
                    React.createElement("table", { className: Utilities_1.css('ms-DatePicker-table', styles.table), "aria-readonly": 'true', "aria-multiselectable": 'false', "aria-labelledby": monthAndYearId, "aria-activedescendant": activeDescendantId },
                        React.createElement("thead", null,
                            React.createElement("tr", null, strings.shortDays.map(function (val, index) {
                                return React.createElement("th", { className: Utilities_1.css('ms-DatePicker-weekday', styles.weekday), role: 'grid', scope: 'col', key: index, title: strings.days[(index + firstDayOfWeek) % DAYS_IN_WEEK], "aria-label": strings.days[(index + firstDayOfWeek) % DAYS_IN_WEEK] }, strings.shortDays[(index + firstDayOfWeek) % DAYS_IN_WEEK]);
                            }))),
                        React.createElement("tbody", null, weeks.map(function (week, weekIndex) {
                            return React.createElement("tr", { key: weekIndex, role: 'row' }, week.map(function (day, dayIndex) {
                                var isNavigatedDate = DateMath_1.compareDates(navigatedDate, day.originalDate);
                                return React.createElement("td", { key: day.key, className: Utilities_1.css((_a = {},
                                        _a['ms-DatePicker-weekBackground ' + styles.weekBackground] = day.isSelected && (dateRangeType === DateValues_1.DateRangeType.Week || dateRangeType === DateValues_1.DateRangeType.WorkWeek),
                                        _a['ms-DatePicker-monthBackground ' + styles.monthBackground + ' ' + _this._getHighlightedCornerStyle(weekCorners, dayIndex, weekIndex)] = day.isInMonth && day.isSelected && dateRangeType === DateValues_1.DateRangeType.Month,
                                        _a['ms-DatePicker-dayBackground ' + styles.dayBackground] = day.isSelected && dateRangeType === DateValues_1.DateRangeType.Day,
                                        _a)) },
                                    React.createElement("div", { className: Utilities_1.css('ms-DatePicker-day', styles.day, (_b = {},
                                            _b['ms-DatePicker-day--disabled ' + styles.dayIsDisabled] = !day.isInBounds,
                                            _b['ms-DatePicker-day--infocus ' + styles.dayIsFocused] = day.isInBounds && day.isInMonth,
                                            _b['ms-DatePicker-day--outfocus ' + styles.dayIsUnfocused] = day.isInBounds && !day.isInMonth,
                                            _b['ms-DatePicker-day--today ' + styles.dayIsToday] = day.isToday,
                                            _b['ms-DatePicker-day--highlighted ' + styles.dayIsHighlighted] = day.isSelected && dateRangeType === DateValues_1.DateRangeType.Day,
                                            _b)), role: 'gridcell', onClick: day.isInBounds ? day.onSelected : undefined, onKeyDown: _this._onDayKeyDown(day.originalDate, weekIndex, dayIndex), "aria-label": dateTimeFormatter.formatMonthDayYear(day.originalDate, strings), id: isNavigatedDate ? activeDescendantId : undefined, "aria-selected": day.isInBounds ? day.isSelected : undefined, "data-is-focusable": day.isInBounds ? true : undefined, ref: isNavigatedDate ? 'navigatedDay' : undefined, key: isNavigatedDate ? 'navigatedDay' : undefined },
                                        React.createElement("span", { "aria-hidden": 'true' }, dateTimeFormatter.formatDay(day.originalDate))));
                                var _a, _b;
                            }));
                        }))))));
            var _c, _d;
        };
        CalendarDay.prototype.focus = function () {
            if (this.refs.navigatedDay) {
                this.refs.navigatedDay.tabIndex = 0;
                this.refs.navigatedDay.focus();
            }
        };
        CalendarDay.prototype._findCornerIndexes = function (week) {
            var cornerIndexes = [];
            for (var i = 0, length_1 = week.length; i < length_1; i++) {
                var day = week[i];
                if (day.isInMonth) {
                    cornerIndexes.push(i);
                }
            }
            if (cornerIndexes.length > 2) {
                cornerIndexes.splice(1, cornerIndexes.length - 2);
            }
            return cornerIndexes;
        };
        CalendarDay.prototype._populateCornerStyles = function (weekCornersStyled, weekIndex, cornerIndexes, singleCornerStyle, leftCornerStyle, rightCornerStyle) {
            var cornersLength = cornerIndexes.length;
            if (cornersLength > 0) {
                if (cornersLength === 1) {
                    weekCornersStyled[weekIndex + '_' + cornerIndexes[0]] = singleCornerStyle;
                }
                else if (cornersLength === 2) {
                    weekCornersStyled[weekIndex + '_' + cornerIndexes[0]] = leftCornerStyle;
                    weekCornersStyled[weekIndex + '_' + cornerIndexes[1]] = rightCornerStyle;
                }
                if (weekIndex === 0) {
                    // check if second week needs corner styles
                    if (cornerIndexes[0] !== 0) {
                        weekCornersStyled['1_0'] = leftCornerStyle;
                    }
                }
                else {
                    // Assume we are on the last week. Check if second-to-last week needs corner styles
                    var lastDayIndex = DAYS_IN_WEEK - 1;
                    if (cornerIndexes[cornersLength - 1] !== lastDayIndex) {
                        weekCornersStyled[(weekIndex - 1) + '_' + lastDayIndex] = rightCornerStyle;
                    }
                }
            }
        };
        CalendarDay.prototype._getWeekCornerStyles = function (weeks) {
            var weekCornersStyled = {};
            var numberOfWeeks = weeks.length;
            var indexesFirstWeek = this._findCornerIndexes(weeks[0]);
            var indexesLastWeek = this._findCornerIndexes(weeks[numberOfWeeks - 1]);
            this._populateCornerStyles(weekCornersStyled, 0 /* week index */, indexesFirstWeek, 'ms-DatePicker-singleTopDate ' + styles.singleTopDate, 'ms-DatePicker-topLeftCornerDate ' + styles.topLeftCornerDate, 'ms-DatePicker-topRightCornerDate ' + styles.topRightCornerDate);
            this._populateCornerStyles(weekCornersStyled, weeks.length - 1 /* week index */, indexesLastWeek, 'ms-DatePicker-singleBottomDate ' + styles.singleBottomDate, 'ms-DatePicker-bottomLeftCornerDate ' + styles.bottomLeftCornerDate, 'ms-DatePicker-bottomRightCornerDate ' + styles.bottomRightCornerDate);
            return weekCornersStyled;
        };
        CalendarDay.prototype._getHighlightedCornerStyle = function (weekCorners, dayIndex, weekIndex) {
            var cornerStyle = weekCorners[weekIndex + '_' + dayIndex] ? weekCorners[weekIndex + '_' + dayIndex] : '';
            return cornerStyle;
        };
        CalendarDay.prototype._navigateMonthEdge = function (ev, date, weekIndex, dayIndex) {
            var _a = this.props, minDate = _a.minDate, maxDate = _a.maxDate;
            var targetDate = undefined;
            if (weekIndex === 0 && ev.which === 38 /* up */) {
                targetDate = DateMath_1.addWeeks(date, -1);
            }
            else if (weekIndex === (this.state.weeks.length - 1) && ev.which === 40 /* down */) {
                targetDate = DateMath_1.addWeeks(date, 1);
            }
            else if (dayIndex === 0 && ev.which === Utilities_1.getRTLSafeKeyCode(37 /* left */)) {
                targetDate = DateMath_1.addDays(date, -1);
            }
            else if (dayIndex === (DAYS_IN_WEEK - 1) && ev.which === Utilities_1.getRTLSafeKeyCode(39 /* right */)) {
                targetDate = DateMath_1.addDays(date, 1);
            }
            // Don't navigate to out-of-bounds date
            if (targetDate && (minDate ? DateMath_1.compareDatePart(minDate, targetDate) < 1 : true) && (maxDate ? DateMath_1.compareDatePart(targetDate, maxDate) < 1 : true)) {
                this.props.onNavigateDate(targetDate, true);
                ev.preventDefault();
            }
        };
        CalendarDay.prototype._onKeyDown = function (callback, ev) {
            if (ev.which === 13 /* enter */ || ev.which === 32 /* space */) {
                callback();
            }
        };
        CalendarDay.prototype._onDayKeyDown = function (originalDate, weekIndex, dayIndex) {
            var _this = this;
            return function (ev) {
                _this._navigateMonthEdge(ev, originalDate, weekIndex, dayIndex);
            };
        };
        CalendarDay.prototype._onSelectDate = function (selectedDate) {
            var _a = this.props, onSelectDate = _a.onSelectDate, dateRangeType = _a.dateRangeType, firstDayOfWeek = _a.firstDayOfWeek, navigatedDate = _a.navigatedDate, autoNavigateOnSelection = _a.autoNavigateOnSelection, minDate = _a.minDate, maxDate = _a.maxDate, workWeekDays = _a.workWeekDays;
            var dateRange = DateMath_1.getDateRangeArray(selectedDate, dateRangeType, firstDayOfWeek, workWeekDays);
            if (dateRangeType !== DateValues_1.DateRangeType.Day) {
                dateRange = this._getBoundedDateRange(dateRange, minDate, maxDate);
            }
            if (onSelectDate) {
                onSelectDate(selectedDate, dateRange);
            }
            // Navigate to next or previous month if needed
            if (autoNavigateOnSelection && selectedDate.getMonth() !== navigatedDate.getMonth()) {
                var compareResult = DateMath_1.compareDatePart(selectedDate, navigatedDate);
                if (compareResult < 0) {
                    this._onSelectPrevMonth();
                }
                else if (compareResult > 0) {
                    this._onSelectNextMonth();
                }
            }
        };
        CalendarDay.prototype._onSelectNextMonth = function () {
            this.props.onNavigateDate(DateMath_1.addMonths(this.props.navigatedDate, 1), false);
        };
        CalendarDay.prototype._onSelectPrevMonth = function () {
            this.props.onNavigateDate(DateMath_1.addMonths(this.props.navigatedDate, -1), false);
        };
        CalendarDay.prototype._onHeaderSelect = function () {
            var onHeaderSelect = this.props.onHeaderSelect;
            if (onHeaderSelect) {
                onHeaderSelect(true);
            }
        };
        CalendarDay.prototype._onHeaderKeyDown = function (ev) {
            var onHeaderSelect = this.props.onHeaderSelect;
            if (onHeaderSelect && (ev.which === 13 /* enter */ || ev.which === 32 /* space */)) {
                onHeaderSelect(true);
            }
        };
        CalendarDay.prototype._onPrevMonthKeyDown = function (ev) {
            this._onKeyDown(this._onSelectPrevMonth, ev);
        };
        CalendarDay.prototype._onNextMonthKeyDown = function (ev) {
            this._onKeyDown(this._onSelectNextMonth, ev);
        };
        CalendarDay.prototype._getWeeks = function (propsToUse) {
            var navigatedDate = propsToUse.navigatedDate, selectedDate = propsToUse.selectedDate, dateRangeType = propsToUse.dateRangeType, firstDayOfWeek = propsToUse.firstDayOfWeek, today = propsToUse.today, minDate = propsToUse.minDate, maxDate = propsToUse.maxDate, showSixWeeksByDefault = propsToUse.showSixWeeksByDefault, workWeekDays = propsToUse.workWeekDays;
            var date = new Date(navigatedDate.getFullYear(), navigatedDate.getMonth(), 1);
            var todaysDate = today || new Date();
            var weeks = [];
            // Cycle the date backwards to get to the first day of the week.
            while (date.getDay() !== firstDayOfWeek) {
                date.setDate(date.getDate() - 1);
            }
            // a flag to indicate whether all days of the week are in the month
            var isAllDaysOfWeekOutOfMonth = false;
            var selectedDates = DateMath_1.getDateRangeArray(selectedDate, dateRangeType, firstDayOfWeek, workWeekDays);
            if (dateRangeType !== DateValues_1.DateRangeType.Day) {
                selectedDates = this._getBoundedDateRange(selectedDates, minDate, maxDate);
            }
            var shouldGetWeeks = true;
            for (var weekIndex = 0; shouldGetWeeks; weekIndex++) {
                var week = [];
                isAllDaysOfWeekOutOfMonth = true;
                for (var dayIndex = 0; dayIndex < DAYS_IN_WEEK; dayIndex++) {
                    var originalDate = new Date(date.toString());
                    var dayInfo = {
                        key: date.toString(),
                        date: date.getDate().toString(),
                        originalDate: originalDate,
                        isInMonth: date.getMonth() === navigatedDate.getMonth(),
                        isToday: DateMath_1.compareDates(todaysDate, date),
                        isSelected: DateMath_1.isInDateRangeArray(date, selectedDates),
                        onSelected: this._onSelectDate.bind(this, originalDate),
                        isInBounds: (minDate ? DateMath_1.compareDatePart(minDate, date) < 1 : true) && (maxDate ? DateMath_1.compareDatePart(date, maxDate) < 1 : true)
                    };
                    week.push(dayInfo);
                    if (dayInfo.isInMonth) {
                        isAllDaysOfWeekOutOfMonth = false;
                    }
                    date.setDate(date.getDate() + 1);
                }
                // We append the condition of the loop depending upon the showSixWeeksByDefault prop.
                shouldGetWeeks = showSixWeeksByDefault ? (!isAllDaysOfWeekOutOfMonth || weekIndex <= 5) : !isAllDaysOfWeekOutOfMonth;
                if (shouldGetWeeks) {
                    weeks.push(week);
                }
            }
            return weeks;
        };
        CalendarDay.prototype._getBoundedDateRange = function (dateRange, minDate, maxDate) {
            var boundedDateRange = dateRange.slice();
            if (minDate) {
                boundedDateRange = boundedDateRange.filter(function (date) { return DateMath_1.compareDatePart(date, minDate) >= 0; });
            }
            if (maxDate) {
                boundedDateRange = boundedDateRange.filter(function (date) { return DateMath_1.compareDatePart(date, maxDate) <= 0; });
            }
            return boundedDateRange;
        };
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onKeyDown", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onDayKeyDown", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onSelectDate", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onSelectNextMonth", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onSelectPrevMonth", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onHeaderSelect", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onHeaderKeyDown", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onPrevMonthKeyDown", null);
        tslib_1.__decorate([
            Utilities_1.autobind
        ], CalendarDay.prototype, "_onNextMonthKeyDown", null);
        return CalendarDay;
    }(Utilities_1.BaseComponent));
    exports.CalendarDay = CalendarDay;
});
//# sourceMappingURL=CalendarDay.js.map