"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var vdom_1 = require("@dojo/framework/core/vdom");
var util_1 = require("../common/util");
var date_utils_1 = require("./date-utils");
var index_1 = require("../icon/index");
var Calendar_1 = require("./nls/Calendar");
var css = require("../theme/default/calendar.m.css");
var baseCss = require("../common/styles/base.m.css");
var iconCss = require("../theme/default/icon.m.css");
var theme_1 = require("../middleware/theme");
var icache_1 = require("@dojo/framework/core/middleware/icache");
var focus_1 = require("@dojo/framework/core/middleware/focus");
var i18n_1 = require("@dojo/framework/core/middleware/i18n");
var FirstDayOfWeek;
(function (FirstDayOfWeek) {
    FirstDayOfWeek[FirstDayOfWeek["sunday"] = 0] = "sunday";
    FirstDayOfWeek[FirstDayOfWeek["monday"] = 1] = "monday";
    FirstDayOfWeek[FirstDayOfWeek["tuesday"] = 2] = "tuesday";
    FirstDayOfWeek[FirstDayOfWeek["wednesday"] = 3] = "wednesday";
    FirstDayOfWeek[FirstDayOfWeek["thursday"] = 4] = "thursday";
    FirstDayOfWeek[FirstDayOfWeek["friday"] = 5] = "friday";
    FirstDayOfWeek[FirstDayOfWeek["saturday"] = 6] = "saturday";
})(FirstDayOfWeek = exports.FirstDayOfWeek || (exports.FirstDayOfWeek = {}));
var DEFAULT_MONTHS = [
    { short: 'janShort', long: 'january' },
    { short: 'febShort', long: 'february' },
    { short: 'marShort', long: 'march' },
    { short: 'aprShort', long: 'april' },
    { short: 'mayShort', long: 'may' },
    { short: 'junShort', long: 'june' },
    { short: 'julShort', long: 'july' },
    { short: 'augShort', long: 'august' },
    { short: 'sepShort', long: 'september' },
    { short: 'octShort', long: 'october' },
    { short: 'novShort', long: 'november' },
    { short: 'decShort', long: 'december' }
];
var DEFAULT_WEEKDAYS = [
    { short: 'sunShort', long: 'sunday' },
    { short: 'monShort', long: 'monday' },
    { short: 'tueShort', long: 'tuesday' },
    { short: 'wedShort', long: 'wednesday' },
    { short: 'thuShort', long: 'thursday' },
    { short: 'friShort', long: 'friday' },
    { short: 'satShort', long: 'saturday' }
];
/**
 * Enum for next/previous buttons
 */
var Paging;
(function (Paging) {
    Paging["next"] = "next";
    Paging["previous"] = "previous";
})(Paging || (Paging = {}));
/**
 * Enum for month or year controls
 */
var Controls;
(function (Controls) {
    Controls["month"] = "month";
    Controls["year"] = "year";
})(Controls || (Controls = {}));
var BASE_YEAR = 2000;
exports.CalendarCell = vdom_1.create({ theme: theme_1.default }).properties()(function CalendarCell(_a) {
    var theme = _a.middleware.theme, properties = _a.properties;
    var themeCss = theme.classes(css);
    var _b = properties(), callFocus = _b.callFocus, date = _b.date, _c = _b.focusable, focusable = _c === void 0 ? false : _c, _d = _b.selected, selected = _d === void 0 ? false : _d, onFocusCalled = _b.onFocusCalled, _e = _b.disabled, disabled = _e === void 0 ? false : _e, _f = _b.outOfRange, outOfRange = _f === void 0 ? false : _f, _g = _b.today, today = _g === void 0 ? false : _g;
    function onClick(event) {
        event.stopPropagation();
        var _a = properties(), date = _a.date, _b = _a.disabled, disabled = _b === void 0 ? false : _b, onClick = _a.onClick;
        onClick && onClick(date, disabled);
    }
    function onKeyDown(event) {
        event.stopPropagation();
        var onKeyDown = properties().onKeyDown;
        onKeyDown &&
            onKeyDown(event.which, function () {
                event.preventDefault();
            });
    }
    if (callFocus) {
        onFocusCalled && onFocusCalled();
    }
    return (vdom_1.tsx("td", { key: "root", focus: callFocus, role: "gridcell", "aria-selected": selected ? 'true' : 'false', tabIndex: focusable ? 0 : -1, classes: [
            themeCss.date,
            disabled || outOfRange ? themeCss.inactiveDate : null,
            outOfRange ? themeCss.outOfRange : null,
            selected ? themeCss.selectedDate : null,
            today ? themeCss.todayDate : null
        ], onclick: onClick, onkeydown: onKeyDown },
        vdom_1.tsx("span", null, "" + date)));
});
exports.DatePicker = vdom_1.create({ theme: theme_1.default, focus: focus_1.default, icache: icache_1.default }).properties()(function DatePicker(_a) {
    var _b = _a.middleware, theme = _b.theme, focus = _b.focus, icache = _b.icache, properties = _a.properties, id = _a.id;
    var themeCss = theme.classes(css);
    var _c = properties(), _d = _c.labelId, labelId = _d === void 0 ? id + "_label" : _d, labels = _c.labels, month = _c.month, year = _c.year;
    var keyWithFocus = icache.get('keyWithFocus');
    var monthPopupOpen = icache.getOrSet('monthPopupOpen', false);
    var yearPopupOpen = icache.getOrSet('yearPopupOpen', false);
    var yearPage = icache.getOrSet('yearPage', 0);
    function closeMonthPopup(event) {
        if (event) {
            event.stopPropagation();
        }
        var onPopupChange = properties().onPopupChange;
        icache.set('keyWithFocus', 'month-button');
        icache.set('monthPopupOpen', false);
        focus.focus();
        onPopupChange && onPopupChange(getPopupState());
    }
    function closeYearPopup(event) {
        if (event) {
            event.stopPropagation();
        }
        var onPopupChange = properties().onPopupChange;
        icache.set('yearPopupOpen', false);
        icache.set('keyWithFocus', 'year-button');
        focus.focus();
        onPopupChange && onPopupChange(getPopupState());
    }
    function getMonthInputKey(month) {
        return id + "_month_input_" + month;
    }
    function getPopupState() {
        var monthPopupOpen = icache.get('monthPopupOpen');
        var yearPopupOpen = icache.get('yearPopupOpen');
        return !!monthPopupOpen || !!yearPopupOpen;
    }
    function getYearInputKey(year) {
        return id + "_year_input_" + year;
    }
    function getYearRange() {
        var _a = properties(), year = _a.year, _b = _a.yearRange, yearRange = _b === void 0 ? 20 : _b;
        var offset = ((year - BASE_YEAR) % yearRange) - yearRange * yearPage;
        if (year >= BASE_YEAR) {
            return { first: year - offset, last: year + yearRange - offset };
        }
        else {
            return { first: year - (yearRange + offset), last: year - offset };
        }
    }
    function onMonthButtonClick(event) {
        event.stopPropagation();
        monthPopupOpen ? closeMonthPopup() : openMonthPopup();
    }
    function onMonthRadioChange(event) {
        event.stopPropagation();
        var onRequestMonthChange = properties().onRequestMonthChange;
        onRequestMonthChange &&
            onRequestMonthChange(parseInt(event.target.value, 10));
    }
    function onPopupKeyDown(event) {
        event.stopPropagation();
        // close popup on escape, or if a value is selected with enter/space
        if (event.which === util_1.Keys.Escape ||
            event.which === util_1.Keys.Enter ||
            event.which === util_1.Keys.Space) {
            event.preventDefault();
            monthPopupOpen && closeMonthPopup();
            yearPopupOpen && closeYearPopup();
        }
    }
    function onYearButtonClick(event) {
        event.stopPropagation();
        yearPopupOpen ? closeYearPopup() : openYearPopup();
    }
    function onYearPageDown(event) {
        event.stopPropagation();
        icache.set('yearPage', yearPage - 1);
    }
    function onYearPageUp(event) {
        event.stopPropagation();
        icache.set('yearPage', yearPage + 1);
    }
    function onYearRadioChange(event) {
        event.stopPropagation();
        var _a = properties(), onRequestYearChange = _a.onRequestYearChange, month = _a.month, minDate = _a.minDate, maxDate = _a.maxDate, onRequestMonthChange = _a.onRequestMonthChange;
        var newYear = parseInt(event.target.value, 10);
        if (!monthInMinMax(newYear, month)) {
            // we know the year is valid but the month is out of range
            if (minDate && newYear === minDate.getFullYear()) {
                onRequestMonthChange && onRequestMonthChange(minDate.getMonth());
            }
            else if (maxDate && newYear === maxDate.getFullYear()) {
                onRequestMonthChange && onRequestMonthChange(maxDate.getMonth());
            }
        }
        icache.set('yearPage', 0);
        onRequestYearChange && onRequestYearChange(newYear);
    }
    function openMonthPopup() {
        var _a = properties(), month = _a.month, onPopupChange = _a.onPopupChange;
        icache.set('monthPopupOpen', true);
        icache.set('yearPopupOpen', false);
        icache.set('keyWithFocus', getMonthInputKey(month));
        focus.focus();
        onPopupChange && onPopupChange(getPopupState());
    }
    function openYearPopup() {
        var _a = properties(), year = _a.year, onPopupChange = _a.onPopupChange;
        icache.set('yearPopupOpen', true);
        icache.set('monthPopupOpen', false);
        icache.set('keyWithFocus', getYearInputKey(year));
        focus.focus();
        onPopupChange && onPopupChange(getPopupState());
    }
    function monthInMinMax(year, month) {
        var _a = properties(), minDate = _a.minDate, maxDate = _a.maxDate;
        return date_utils_1.monthInMin(year, month, minDate) && date_utils_1.monthInMax(year, month, maxDate);
    }
    function yearInMinMax(year) {
        var _a = properties(), minDate = _a.minDate, maxDate = _a.maxDate;
        var minYear = minDate ? minDate.getFullYear() : year;
        var maxYear = maxDate ? maxDate.getFullYear() : year;
        return year >= minYear && year <= maxYear;
    }
    function renderControlsTrigger(type) {
        var _a = properties(), month = _a.month, monthNames = _a.monthNames, year = _a.year;
        var content = type === Controls.month ? monthNames[month].long : "" + year;
        var open = type === Controls.month ? monthPopupOpen : yearPopupOpen;
        var onclick = type === Controls.month ? onMonthButtonClick : onYearButtonClick;
        var key = type + "-button";
        return (vdom_1.tsx("button", { key: key, "aria-controls": id + "_" + type + "_dialog", "aria-expanded": open ? 'true' : 'false', "aria-haspopup": "true", id: id + "_" + type + "_button", classes: [
                themeCss[type + "Trigger"],
                open ? themeCss[type + "TriggerActive"] : null
            ], focus: keyWithFocus === key ? focus.shouldFocus : undefined, role: "menuitem", type: "button", onclick: onclick }, content));
    }
    function renderMonthLabel(month, year) {
        var _a = properties(), monthNames = _a.monthNames, renderMonthLabel = _a.renderMonthLabel;
        return renderMonthLabel
            ? renderMonthLabel(month, year)
            : monthNames[month].long + " " + year;
    }
    function renderMonthRadios() {
        var _a = properties(), year = _a.year, month = _a.month, monthNames = _a.monthNames;
        return monthNames.map(function (_a, i) {
            var short = _a.short, long = _a.long;
            var key = getMonthInputKey(i);
            return (vdom_1.tsx("label", { key: id + "_month_radios_" + i, classes: [
                    themeCss.monthRadio,
                    i === month ? themeCss.monthRadioChecked : null
                ], for: getMonthInputKey(i), onmouseup: closeMonthPopup },
                vdom_1.tsx("input", { checked: i === month, classes: themeCss.monthRadioInput, id: key, key: key, name: id + "_month_radios", focus: keyWithFocus === key ? focus.shouldFocus : undefined, tabIndex: monthPopupOpen ? 0 : -1, type: "radio", value: "" + i, disabled: !monthInMinMax(year, i), onchange: onMonthRadioChange }),
                vdom_1.tsx("abbr", { classes: themeCss.monthRadioLabel, title: long }, short)));
        });
    }
    function renderPagingButtonContent(type) {
        var _a = properties(), labels = _a.labels, classes = _a.classes, variant = _a.variant;
        var iconType = type === Paging.next ? 'rightIcon' : 'leftIcon';
        var labelText = type === Paging.next ? labels.nextYears : labels.previousYears;
        return [
            vdom_1.tsx(index_1.default, { type: iconType, theme: theme.compose(iconCss, css, 'datePickerPaging'), classes: classes, variant: variant }),
            vdom_1.tsx("span", { classes: baseCss.visuallyHidden }, labelText)
        ];
    }
    function renderYearRadios() {
        var year = properties().year;
        var radios = [];
        var yearLimits = getYearRange();
        for (var i = yearLimits.first; i < yearLimits.last; i++) {
            var key = getYearInputKey(i);
            radios.push(vdom_1.tsx("label", { key: id + "_year_radios_" + i, classes: [
                    themeCss.yearRadio,
                    i === year ? themeCss.yearRadioChecked : null
                ], for: getYearInputKey(i), onmouseup: closeYearPopup },
                vdom_1.tsx("input", { checked: i === year, classes: themeCss.yearRadioInput, id: key, key: key, name: id + "_year_radios", focus: keyWithFocus === key ? focus.shouldFocus : undefined, tabIndex: yearPopupOpen ? 0 : -1, type: "radio", value: "" + i, disabled: !yearInMinMax(i), onchange: onYearRadioChange }),
                vdom_1.tsx("abbr", { classes: themeCss.yearRadioLabel }, "" + i)));
        }
        return radios;
    }
    return (vdom_1.tsx("div", { classes: themeCss.datePicker },
        vdom_1.tsx("div", { classes: themeCss.topMatter, role: "menubar" },
            vdom_1.tsx("label", { id: labelId, classes: [baseCss.visuallyHidden], "aria-live": "polite", "aria-atomic": "false" }, renderMonthLabel(month, year)),
            renderControlsTrigger(Controls.month),
            renderControlsTrigger(Controls.year)),
        vdom_1.tsx("div", { key: "month-grid", "aria-hidden": monthPopupOpen ? 'false' : 'true', "aria-labelledby": id + "_month_button", classes: [themeCss.monthGrid, !monthPopupOpen ? baseCss.visuallyHidden : null], id: id + "_month_dialog", role: "dialog" },
            vdom_1.tsx("fieldset", { classes: themeCss.monthFields, onkeydown: onPopupKeyDown },
                vdom_1.tsx("legend", { classes: baseCss.visuallyHidden }, labels.chooseMonth),
                renderMonthRadios())),
        vdom_1.tsx("div", { key: "year-grid", "aria-hidden": yearPopupOpen ? 'false' : 'true', "aria-labelledby": id + "_year_button", classes: [themeCss.yearGrid, !yearPopupOpen ? baseCss.visuallyHidden : null], id: id + "_year_dialog", role: "dialog" },
            vdom_1.tsx("fieldset", { classes: themeCss.yearFields, onkeydown: onPopupKeyDown },
                vdom_1.tsx("legend", { classes: [baseCss.visuallyHidden] }, labels.chooseYear),
                renderYearRadios())),
        vdom_1.tsx("div", { classes: themeCss.controls },
            vdom_1.tsx("button", { classes: themeCss.previous, tabindex: yearPopupOpen ? 0 : -1, type: "button", onclick: onYearPageDown, disabled: !yearInMinMax(year - 1) }, renderPagingButtonContent(Paging.previous)),
            vdom_1.tsx("button", { classes: themeCss.next, tabindex: yearPopupOpen ? 0 : -1, type: "button", onclick: onYearPageUp, disabled: !yearInMinMax(year + 1) }, renderPagingButtonContent(Paging.next)))));
});
var factory = vdom_1.create({
    icache: icache_1.createICacheMiddleware(),
    i18n: i18n_1.default,
    theme: theme_1.default,
    focus: focus_1.default
})
    .properties()
    .children();
exports.Calendar = factory(function Calendar(_a) {
    var _b;
    var _c = _a.middleware, icache = _c.icache, i18n = _c.i18n, theme = _c.theme, focus = _c.focus, properties = _a.properties, id = _a.id, children = _a.children;
    var themeCss = theme.classes(css);
    var commonMessages = i18n.localize(Calendar_1.default).messages;
    var _d = properties(), _e = _d.labels, labels = _e === void 0 ? i18n.localize(Calendar_1.default).messages : _e, _f = _d.aria, aria = _f === void 0 ? {} : _f, minDate = _d.minDate, maxDate = _d.maxDate, initialValue = _d.initialValue, _g = _d.weekdayNames, weekdayNames = _g === void 0 ? getWeekdays(commonMessages) : _g, _h = _d.firstDayOfWeek, firstDayOfWeek = _h === void 0 ? 0 : _h;
    var _j = properties(), value = _j.value, month = _j.month, year = _j.year;
    var _k = children()[0] || {}, monthLabel = _k.monthLabel, weekdayCell = _k.weekdayCell;
    var defaultDate = initialValue || new Date();
    var _l = properties(), _m = _l.initialYear, initialYear = _m === void 0 ? defaultDate.getFullYear() : _m, _o = _l.initialMonth, initialMonth = _o === void 0 ? defaultDate.getMonth() : _o;
    var existingInitialValue = icache.get('initialValue');
    var existingInitialMonth = icache.get('initialMonth');
    var existingInitialYear = icache.get('initialYear');
    var callDateFocus = icache.getOrSet('callDateFocus', false);
    var focusedDay = icache.getOrSet('focusedDay', 1);
    var monthLabelId = icache.getOrSet('monthLabelId', id);
    var popupOpen = icache.getOrSet('popupOpen', false);
    var shouldFocus = focus.shouldFocus();
    if (!value) {
        value = icache.get('value') || new Date();
        if (!initialValue && !existingInitialValue) {
            value = date_utils_1.toDate(defaultDate);
            if (date_utils_1.isOutOfDateRange(value, minDate, maxDate)) {
                value = date_utils_1.toDate(maxDate);
            }
            icache.set('initialValue', value);
            icache.set('value', value);
        }
        if (initialValue && initialValue !== existingInitialValue) {
            value = date_utils_1.toDate(initialValue);
            icache.set('initialValue', date_utils_1.toDate(initialValue));
            icache.set('value', value);
        }
    }
    if (typeof month === 'undefined') {
        if (initialMonth !== existingInitialMonth) {
            icache.set('initialMonth', initialMonth);
            icache.set('month', initialMonth);
        }
    }
    if (typeof year === 'undefined') {
        if (initialYear !== existingInitialYear) {
            icache.set('initialYear', initialYear);
            icache.set('year', initialYear);
        }
    }
    (_b = getMonthYear(), month = _b.month, year = _b.year);
    var weekdayOrder = [];
    for (var i = firstDayOfWeek; i < firstDayOfWeek + 7; i++) {
        weekdayOrder.push(i > 6 ? i - 7 : i);
    }
    var weekdays = weekdayOrder.map(function (order) { return (vdom_1.tsx("th", { role: "columnheader", classes: themeCss.weekday }, renderWeekdayCell(weekdayNames[order]))); });
    function onValueChange(newValue) {
        var onValue = properties().onValue;
        icache.set('value', newValue);
        onValue && onValue(newValue);
    }
    function onMonthChange(newMonth) {
        var onMonth = properties().onMonth;
        icache.set('month', newMonth);
        onMonth && onMonth(newMonth);
    }
    function onYearChange(newYear) {
        var onYear = properties().onYear;
        icache.set('year', newYear);
        onYear && onYear(newYear);
    }
    function getMonthLength(month, year) {
        var lastDate = new Date(year, month + 1, 0);
        return lastDate.getDate();
    }
    function getMonths(commonMessages) {
        return DEFAULT_MONTHS.map(function (month) { return ({
            short: commonMessages[month.short],
            long: commonMessages[month.long]
        }); });
    }
    function getMonthYear() {
        var _a = properties(), month = _a.month, year = _a.year, value = _a.value;
        var selectedDate = value || icache.getOrSet('value', new Date());
        month = typeof month === 'number' ? month : icache.get('month');
        year = typeof year === 'number' ? year : icache.get('year');
        return {
            month: typeof month === 'number' ? month : selectedDate.getMonth(),
            year: typeof year === 'number' ? year : selectedDate.getFullYear()
        };
    }
    function getWeekdays(commonMessages) {
        return DEFAULT_WEEKDAYS.map(function (weekday) { return ({
            short: commonMessages[weekday.short],
            long: commonMessages[weekday.long]
        }); });
    }
    function goToDate(day) {
        var _a = getMonthYear(), month = _a.month, year = _a.year;
        var currentMonthLength = getMonthLength(month, year);
        var previousMonthLength = getMonthLength(month - 1, year);
        ensureDayIsInMinMax(new Date(year, month, day), function (updatedDay) { return (day = updatedDay); });
        if (day < 1) {
            onMonthDecrement();
            day += previousMonthLength;
        }
        else if (day > currentMonthLength) {
            onMonthIncrement();
            day -= currentMonthLength;
        }
        icache.set('focusedDay', day);
        icache.set('callDateFocus', true);
    }
    function onDateClick(date, disabled) {
        var _a;
        var _b = getMonthYear(), month = _b.month, year = _b.year;
        if (disabled) {
            (_a = date < 15 ? onMonthIncrement() : onMonthDecrement(), month = _a.month, year = _a.year);
            icache.set('callDateFocus', true);
        }
        icache.set('focusedDay', date);
        var dateValue = new Date(year, month, date);
        onValueChange(dateValue);
    }
    function onDateFocusCalled() {
        icache.set('callDateFocus', false);
    }
    function onDateKeyDown(key, preventDefault) {
        var _a = getMonthYear(), month = _a.month, year = _a.year;
        switch (key) {
            case util_1.Keys.Up:
                preventDefault();
                goToDate(focusedDay - 7);
                break;
            case util_1.Keys.Down:
                preventDefault();
                goToDate(focusedDay + 7);
                break;
            case util_1.Keys.Left:
                preventDefault();
                goToDate(focusedDay - 1);
                break;
            case util_1.Keys.Right:
                preventDefault();
                goToDate(focusedDay + 1);
                break;
            case util_1.Keys.PageUp:
                preventDefault();
                goToDate(1);
                break;
            case util_1.Keys.PageDown:
                preventDefault();
                var monthLength = getMonthLength(month, year);
                goToDate(monthLength);
                break;
            case util_1.Keys.Enter:
            case util_1.Keys.Space:
                onValueChange(new Date(year, month, focusedDay));
        }
    }
    function onMonthDecrement() {
        var _a = getMonthYear(), month = _a.month, year = _a.year;
        var newYear = month === 0 ? year - 1 : year;
        var newMonth = month === 0 ? 11 : month - 1;
        onMonthChange(newMonth);
        if (newYear !== year) {
            onYearChange(newYear);
        }
        return { month: newMonth, year: newYear };
    }
    function onMonthIncrement() {
        var _a = getMonthYear(), month = _a.month, year = _a.year;
        var newYear = month === 11 ? year + 1 : year;
        var newMonth = month === 11 ? 0 : month + 1;
        onMonthChange(newMonth);
        if (newYear !== year) {
            onYearChange(newYear);
        }
        return { month: newMonth, year: newYear };
    }
    function onMonthPageDown(event) {
        event.stopPropagation();
        onMonthDecrement();
    }
    function onMonthPageUp(event) {
        event.stopPropagation();
        onMonthIncrement();
    }
    function ensureDayIsInMinMax(newDate, update) {
        var _a = properties(), minDate = _a.minDate, maxDate = _a.maxDate;
        if (minDate && newDate < minDate) {
            update(minDate.getDate());
        }
        else if (maxDate && newDate > maxDate) {
            update(maxDate.getDate());
        }
    }
    function renderDateGrid(selectedDate) {
        var _a = getMonthYear(), month = _a.month, year = _a.year;
        var _b = properties().firstDayOfWeek, firstDayOfWeek = _b === void 0 ? 0 : _b;
        ensureDayIsInMinMax(new Date(year, month, focusedDay), function (newDay) {
            return icache.set('focusedDay', newDay);
        });
        var currentMonthLength = getMonthLength(month, year);
        var previousMonthLength = getMonthLength(month - 1, year);
        var currentMonthStartDay = new Date(year, month, 1).getDay();
        var initialWeekday = currentMonthStartDay - firstDayOfWeek < 0
            ? currentMonthStartDay - firstDayOfWeek + 7
            : currentMonthStartDay - firstDayOfWeek;
        var todayString = new Date().toDateString();
        var dayIndex = 0;
        var isCurrentMonth = currentMonthStartDay === firstDayOfWeek;
        var cellMonth = isCurrentMonth ? month : month - 1;
        var date = isCurrentMonth ? 0 : previousMonthLength - initialWeekday;
        var isSelectedDay;
        var isToday;
        var weeks = [];
        var days;
        var dateObj;
        var dateString;
        var weekday;
        for (var week = 0; week < 6; week++) {
            days = [];
            for (weekday = 0; weekday < 7; weekday++) {
                // find the next date
                // if we've reached the end of the previous month, reset to 1
                if (date > dayIndex && date >= previousMonthLength) {
                    date = 1;
                    cellMonth++;
                }
                // if we've reached the end of the current month, reset to 1
                else if (date <= dayIndex && date >= currentMonthLength) {
                    date = 1;
                    cellMonth++;
                }
                else {
                    date++;
                }
                // set isSelectedDay if the dates match
                dateObj = new Date(year, cellMonth, date);
                dateString = dateObj.toDateString();
                isSelectedDay = Boolean(selectedDate && dateString === selectedDate.toDateString());
                isCurrentMonth = month === cellMonth;
                isToday = dateString === todayString;
                days.push(renderDateCell(dateObj, dayIndex++, isSelectedDay, isCurrentMonth, isToday));
            }
            weeks.push(vdom_1.tsx("tr", null, days));
        }
        return weeks;
    }
    function renderDateCell(dateObj, index, selected, currentMonth, today) {
        var _a = properties(), minDate = _a.minDate, maxDate = _a.maxDate, theme = _a.theme, classes = _a.classes, variant = _a.variant;
        var date = dateObj.getDate();
        var outOfRange = date_utils_1.isOutOfDateRange(dateObj, minDate, maxDate);
        var focusable = currentMonth && date === icache.get('focusedDay');
        return (vdom_1.tsx(exports.CalendarCell, { classes: classes, variant: variant, key: "date-" + index, callFocus: (callDateFocus || shouldFocus) && focusable, date: date, outOfRange: outOfRange, focusable: focusable, disabled: !currentMonth, selected: selected, theme: theme, today: today, onClick: outOfRange ? undefined : onDateClick, onFocusCalled: onDateFocusCalled, onKeyDown: onDateKeyDown }));
    }
    function renderDatePicker(commonMessages, labels) {
        var _a = properties(), _b = _a.monthNames, monthNames = _b === void 0 ? getMonths(commonMessages) : _b, theme = _a.theme, classes = _a.classes, variant = _a.variant, minDate = _a.minDate, maxDate = _a.maxDate;
        var _c = getMonthYear(), month = _c.month, year = _c.year;
        return (vdom_1.tsx(exports.DatePicker, { key: "date-picker", classes: classes, variant: variant, labelId: monthLabelId, labels: labels, month: month, monthNames: monthNames, renderMonthLabel: monthLabel, theme: theme, year: year, minDate: minDate, maxDate: maxDate, onPopupChange: function (open) {
                icache.set('popupOpen', open);
            }, onRequestMonthChange: function (requestMonth) {
                onMonthChange(requestMonth);
            }, onRequestYearChange: function (requestYear) {
                onYearChange(requestYear);
            } }));
    }
    function renderPagingButtonContent(type, labels) {
        var _a = properties(), classes = _a.classes, variant = _a.variant;
        var iconType = type === Paging.next ? 'rightIcon' : 'leftIcon';
        var labelText = type === Paging.next ? labels.nextMonth : labels.previousMonth;
        return [
            vdom_1.tsx(index_1.default, { type: iconType, theme: theme.compose(iconCss, css, 'calendarPaging'), classes: classes, variant: variant }),
            vdom_1.tsx("span", { classes: [baseCss.visuallyHidden] }, labelText)
        ];
    }
    function renderWeekdayCell(day) {
        return weekdayCell ? (weekdayCell(day)) : (vdom_1.tsx("abbr", { classes: themeCss.abbr, title: day.long }, day.short));
    }
    return (vdom_1.tsx("div", tslib_1.__assign({ classes: [theme.variant(), themeCss.root] }, util_1.formatAriaProperties(aria)),
        renderDatePicker(commonMessages, labels),
        vdom_1.tsx("table", { cellspacing: "0", cellpadding: "0", role: "grid", "aria-labelledby": monthLabelId, classes: [themeCss.dateGrid, popupOpen ? baseCss.visuallyHidden : null] },
            vdom_1.tsx("thead", null,
                vdom_1.tsx("tr", null, weekdays)),
            vdom_1.tsx("tbody", null, renderDateGrid(value))),
        vdom_1.tsx("div", { classes: [themeCss.controls, popupOpen ? baseCss.visuallyHidden : null] },
            vdom_1.tsx("button", { classes: themeCss.previous, tabIndex: popupOpen ? -1 : 0, type: "button", disabled: !date_utils_1.monthInMin(year, month - 1, minDate), onclick: onMonthPageDown }, renderPagingButtonContent(Paging.previous, labels)),
            vdom_1.tsx("button", { classes: themeCss.next, tabIndex: popupOpen ? -1 : 0, type: "button", disabled: !date_utils_1.monthInMax(year, month + 1, maxDate), onclick: onMonthPageUp }, renderPagingButtonContent(Paging.next, labels)))));
});
exports.default = exports.Calendar;

/*# sourceMappingURL=index.js.map*/