    /**
    A date picker component which shows a Date Picker on the screen. This class extends from {@link Ext.picker.Picker}
    and {@link Ext.Sheet} so it is a popup.

    This component has no required configurations.
    ## Examples
        @example preview
        var datePicker = Ext.create('Ext.picker.Date');
        datePicker.show();

    You may want to adjust the {@link #yearFrom} and {@link #yearTo} properties:

        @example preview
        var datePicker = Ext.create('Ext.picker.Date', {
            yearFrom: 2000,
            yearTo  : 2015
        });
        datePicker.show();

    You can set the value of the {@link Ext.picker.Date} to the current date using `new Date()`:

        @example preview
        var datePicker = Ext.create('Ext.picker.Date', {
            value: new Date()
        });
        datePicker.show();

    And you can hide the titles from each of the slots by using the {@link #useTitles} configuration:

        @example preview
        var datePicker = Ext.create('Ext.picker.Date', {
            useTitles: false
        });
        datePicker.show();

     */
    Ext.define('Ext.picker.Date', {
        extend: 'Ext.picker.Picker',
        xtype: 'datepicker',
        alternateClassName: 'Ext.DatePicker',
        requires: ['Ext.DateExtras'],

        config: {
            /**
             * @cfg {Number} yearFrom
             * The start year for the date picker.
             * @accessor
             */
            yearFrom: 1980,

            /**
             * @cfg {Number} yearTo
             * The last year for the date picker.
             * @default the current year (new Date().getFullYear())
             * @accessor
             */
            yearTo: new Date().getFullYear(),

            /**
             * @cfg {String} monthText
             * The label to show for the month column.
             * @accessor
             */
            monthText: 'Month',

            /**
             * @cfg {String} dayText
             * The label to show for the day column.
             * @accessor
             */
            dayText: 'Day',

            /**
             * @cfg {String} yearText
             * The label to show for the year column.
             * @accessor
             */
            yearText: 'Year',

            /**
             * @cfg {Array} slotOrder
             * An array of strings that specifies the order of the slots.
             * @accessor
             */
            slotOrder: ['month', 'day', 'year']

            /**
             * @cfg {Object/Date} value
             * Default value for the field and the internal {@link Ext.picker.Date} component. Accepts an object of 'year',
             * 'month' and 'day' values, all of which should be numbers, or a {@link Date}.
             *
             * Examples:
             * {year: 1989, day: 1, month: 5} = 1st May 1989.
             * new Date() = current date
             * @accessor
             */

            /**
             * @cfg {Array} slots
             * @hide
             * @accessor
             */
        },

        setValue: function(value, animated) {
            if (Ext.isDate(value)) {
                value = {
                    day  : value.getDate(),
                    month: value.getMonth() + 1,
                    year : value.getFullYear()
                };
            }

            this.callParent([value, animated]);
        },

        getValue: function() {
            var values = {},
                daysInMonth, day,
                items = this.getItems().items,
                ln = items.length,
                item, i;

            for (i = 0; i < ln; i++) {
                item = items[i];
                if (item instanceof Ext.picker.Slot) {
                    values[item.getName()] = item.getValue();
                }
            }

            daysInMonth = this.getDaysInMonth(values.month, values.year);
            day = Math.min(values.day, daysInMonth);

            return new Date(values.year, values.month - 1, day);
        },

        /**
         * Updates the yearFrom configuration
         */
        updateYearFrom: function() {
            if (this.initialized) {
                this.createSlots();
            }
        },

        /**
         * Updates the yearTo configuration
         */
        updateYearTo: function() {
            if (this.initialized) {
                this.createSlots();
            }
        },

        /**
         * Updates the monthText configuration
         */
        updateMonthText: function(newMonthText, oldMonthText) {
            var innerItems = this.getInnerItems,
                ln = innerItems.length,
                item, i;

            //loop through each of the current items and set the title on the correct slice
            if (this.initialized) {
                for (i = 0; i < ln; i++) {
                    item = innerItems[i];

                    if ((typeof item.title == "string" && item.title == oldMonthText) || (item.title.html == oldMonthText)) {
                        item.setTitle(newMonthText);
                    }
                }
            }
        },

        /**
         * Updates the dayText configuraton
         */
        updateDayText: function(newDayText, oldDayText) {
            var innerItems = this.getInnerItems,
                ln = innerItems.length,
                item, i;

            //loop through each of the current items and set the title on the correct slice
            if (this.initialized) {
                for (i = 0; i < ln; i++) {
                    item = innerItems[i];

                    if ((typeof item.title == "string" && item.title == oldDayText) || (item.title.html == oldDayText)) {
                        item.setTitle(newDayText);
                    }
                }
            }
        },

        /**
         * Updates the yearText configuration
         */
        updateYearText: function(yearText) {
            var innerItems = this.getInnerItems,
                ln = innerItems.length,
                item, i;

            //loop through each of the current items and set the title on the correct slice
            if (this.initialized) {
                for (i = 0; i < ln; i++) {
                    item = innerItems[i];

                    if (item.title == this.yearText) {
                        item.setTitle(yearText);
                    }
                }
            }
        },

        // @private
        constructor: function() {
            this.callParent(arguments);
            this.createSlots();
        },

        /**
         * Generates all slots for all years specified by this component, and then sets them on the component
         * @private
         */
        createSlots: function() {
            var me        = this,
                slotOrder = this.getSlotOrder(),
                yearsFrom = me.getYearFrom(),
                yearsTo   = me.getYearTo(),
                years     = [],
                days      = [],
                months    = [],
                ln, tmp, i,
                daysInMonth;

            // swap values if user mixes them up.
            if (yearsFrom > yearsTo) {
                tmp = yearsFrom;
                yearsFrom = yearsTo;
                yearsTo = tmp;
            }

            for (i = yearsFrom; i <= yearsTo; i++) {
                years.push({
                    text: i,
                    value: i
                });
            }

            daysInMonth = this.getDaysInMonth(1, new Date().getFullYear());

            for (i = 0; i < daysInMonth; i++) {
                days.push({
                    text: i + 1,
                    value: i + 1
                });
            }

            for (i = 0, ln = Ext.Date.monthNames.length; i < ln; i++) {
                months.push({
                    text: Ext.Date.monthNames[i],
                    value: i + 1
                });
            }

            var slots = [];

            slotOrder.forEach(function(item) {
                slots.push(this.createSlot(item, days, months, years));
            }, this);

            me.setSlots(slots);
        },

        /**
         * Returns a slot config for a specified date.
         * @private
         */
        createSlot: function(name, days, months, years) {
            switch (name) {
                case 'year':
                    return {
                        name: 'year',
                        align: 'center',
                        data: years,
                        title: this.getYearText(),
                        flex: 3
                    };
                case 'month':
                    return {
                        name: name,
                        align: 'right',
                        data: months,
                        title: this.getMonthText(),
                        flex: 4
                    };
                case 'day':
                    return {
                        name: 'day',
                        align: 'center',
                        data: days,
                        title: this.getDayText(),
                        flex: 2
                    };
            }
        },

        // @private
        getDaysInMonth: function(month, year) {
            var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
            return month == 2 && this.isLeapYear(year) ? 29 : daysInMonth[month-1];
        },

        // @private
        isLeapYear: function(year) {
            return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));
        }
    });