/// interval calendar
(function() {

    /**
     * IntervalCalendar is an extension of the CalendarGroup designed specifically
     * for the selection of an interval of dates.
     *
     * @treeNamespace YAHOO.example.calendar
     * @module calendar
     * @since 2.5.2
     * @requires yahoo, dom, event, calendar
     */

    /**
     * IntervalCalendar is an extension of the CalendarGroup designed specifically
     * for the selection of an interval of dates, as opposed to a single date or
     * an arbitrary collection of dates.
     * <p>
     * <b>Note:</b> When using IntervalCalendar, dates should not be selected or
     * deselected using the 'selected' configuration property or any of the
     * CalendarGroup select/deselect methods. Doing so will corrupt the internal
     * state of the control. Instead, use the provided methods setInterval and
     * resetInterval.
     * </p>
     * <p>
     * Similarly, when handling select/deselect/etc. events, do not use the
     * dates passed in the arguments to attempt to keep track of the currently
     * selected interval. Instead, use getInterval.
     * </p>
     *
     * @treeNamespace YAHOO.example.calendar
     * @class IntervalCalendar
     * @extends YAHOO.widget.CalendarGroup
     * @constructor
     * @param {String | HTMLElement} container The id of, or reference to, an HTML DIV element which will contain the control.
     * @param {Object} cfg optional The initial configuration options for the control.
     */
    function IntervalCalendar(container, cfg) {
        /**
         * The interval state, which counts the number of interval endpoints that have
         * been selected (0 to 2).
         *
         * @private
         * @type Number
         */
        this._iState = 0;

        // Must be a multi-select CalendarGroup
        cfg = cfg || {};
        cfg.multi_select = true;

        // Call parent constructor
        IntervalCalendar.superclass.constructor.call(this, container, cfg);

        // Subscribe internal event handlers
        this.beforeSelectEvent.subscribe(this._intervalOnBeforeSelect, this, true);
        this.selectEvent.subscribe(this._intervalOnSelect, this, true);
        this.beforeDeselectEvent.subscribe(this._intervalOnBeforeDeselect, this, true);
        this.deselectEvent.subscribe(this._intervalOnDeselect, this, true);
    }

    /**
     * Default configuration parameters.
     *
     * @property IntervalCalendar._DEFAULT_CONFIG
     * @final
     * @static
     * @private
     * @type Object
     */
    IntervalCalendar._DEFAULT_CONFIG = YAHOO.widget.CalendarGroup._DEFAULT_CONFIG;

    YAHOO.lang.extend(IntervalCalendar, YAHOO.widget.CalendarGroup, {

        /**
         * Returns a string representation of a date which takes into account
         * relevant localization settings and is suitable for use with
         * YAHOO.widget.CalendarGroup and YAHOO.widget.Calendar methods.
         *
         * @method _dateString
         * @private
         * @param {Date} d The JavaScript Date object of which to obtain a string representation.
         * @return {String} The string representation of the JavaScript Date object.
         */
        _dateString : function(d) {
            var a = [];
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_MONTH_POSITION.key)-1] = (d.getMonth() + 1);
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_DAY_POSITION.key)-1] = d.getDate();
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_YEAR_POSITION.key)-1] = d.getFullYear();
            var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_FIELD_DELIMITER.key);
            return a.join(s);
        },

        /**
         * Given a lower and upper date, returns a string representing the interval
         * of dates between and including them, which takes into account relevant
         * localization settings and is suitable for use with
         * YAHOO.widget.CalendarGroup and YAHOO.widget.Calendar methods.
         * <p>
         * <b>Note:</b> No internal checking is done to ensure that the lower date
         * is in fact less than or equal to the upper date.
         * </p>
         *
         * @method _dateIntervalString
         * @private
         * @param {Date} l The lower date of the interval, as a JavaScript Date object.
         * @param {Date} u The upper date of the interval, as a JavaScript Date object.
         * @return {String} The string representing the interval of dates between and
         *                   including the lower and upper dates.
         */
        _dateIntervalString : function(l, u) {
            var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_RANGE_DELIMITER.key);
            return (this._dateString(l)
                + s + this._dateString(u));
        },

        /**
         * Returns the lower and upper dates of the currently selected interval, if an
         * interval is selected.
         *
         * @method getInterval
         * @return {Array} An empty array if no interval is selected; otherwise an array
         *                 consisting of two JavaScript Date objects, the first being the
         *                 lower date of the interval and the second being the upper date.
         */
        getInterval : function() {
            // Get selected dates
            var dates = this.getSelectedDates();
            if(dates.length > 0) {
                // Return lower and upper date in array
                var l = dates[0];
                var u = dates[dates.length - 1];
                return [l, u];
            }
            else {
                // No dates selected, return empty array
                return [];
            }
        },

        /**
         * Sets the currently selected interval by specifying the lower and upper
         * dates of the interval (in either order).
         * <p>
         * <b>Note:</b> The render method must be called after setting the interval
         * for any changes to be seen.
         * </p>
         *
         * @method setInterval
         * @param {Date} d1 A JavaScript Date object.
         * @param {Date} d2 A JavaScript Date object.
         */
        setInterval : function(d1, d2) {
            // Determine lower and upper dates
            var b = (d1 <= d2);
            var l = b ? d1 : d2;
            var u = b ? d2 : d1;
            // Update configuration
            this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
            this._iState = 2;
        },

        /**
         * Resets the currently selected interval.
         * <p>
         * <b>Note:</b> The render method must be called after resetting the interval
         * for any changes to be seen.
         * </p>
         *
         * @method resetInterval
         */
        resetInterval : function() {
            // Update configuration
            this.cfg.setProperty('selected', [], false);
            this._iState = 0;
        },

        /**
         * Handles beforeSelect event.
         *
         * @method _intervalOnBeforeSelect
         * @private
         */
        _intervalOnBeforeSelect : function(t,a,o) {
            // Update interval state
            this._iState = (this._iState + 1) % 3;
            if(this._iState == 0) {
                // If starting over with upcoming selection, first deselect all
                this.deselectAll();
                this._iState++;
            }
        },

        /**
         * Handles selectEvent event.
         *
         * @method _intervalOnSelect
         * @private
         */
        _intervalOnSelect : function(t,a,o) {
            // Get selected dates
            var dates = this.getSelectedDates();
            if(dates.length > 1) {
                /* If more than one date is selected, ensure that the entire interval
                    between and including them is selected */
                var l = dates[0];
                var u = dates[dates.length - 1];
                this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
            }
            // Render changes
            this.render();
        },

        /**
         * Handles beforeDeselect event.
         *
         * @method _intervalOnBeforeDeselect
         * @private
         */
        _intervalOnBeforeDeselect : function(t,a,o) {
            if(this._iState != 0) {
                /* If part of an interval is already selected, then swallow up
                    this event because it is superfluous (see _intervalOnDeselect) */
                return false;
            }
        },

        /**
         * Handles deselectEvent event.
         *
         * @method _intervalOnDeselect
         * @private
         */
        _intervalOnDeselect : function(t,a,o) {
            if(this._iState != 0) {
                // If part of an interval is already selected, then first deselect all
                this._iState = 0;
                this.deselectAll();

                // Get individual date deselected and page containing it
                var d = a[0][0];
                var date = YAHOO.widget.DateMath.getDate(d[0], d[1] - 1, d[2]);
                var page = this.getCalendarPage(date);
                if(page) {
                    // Now (re)select the individual date
                    page.beforeSelectEvent.fire();
                    this.cfg.setProperty('selected', this._dateString(date), false);
                    page.selectEvent.fire([d]);
                }
                // Swallow up since we called deselectAll above
                return false;
            }
        }
    });

    //YAHOO.treeNamespace("example.calendar");
    YAHOO.IntervalCalendar = IntervalCalendar;
})();

function initCal(startDate,endDate){
    var fromDate, toDate, interval,
    today = new Date(),
    cal = new YAHOO.IntervalCalendar("dateRangeSelector", {
        pages:2,
        close:true,
        maxdate:today
    });
    var dateCheck = isDate(startDate.innerHTML, /^([0-9]{4})[\/]([0-9]{2})[\/]([0-9]{2})$/, {
        d: 3,
        m: 2,
        y: 1
    })
    if(dateCheck == 0){
        var start = new Date(startDate.innerHTML)
        end = new Date(endDate.innerHTML);
        cal.setInterval(start,end)
    }
    cal.selectEvent.subscribe(function() {
        interval = this.getInterval();

        if (interval.length == 2) {
            fromDate = interval[0];
            startDate.innerHTML = (fromDate.getMonth() + 1) + "/" + fromDate.getDate() + "/" + fromDate.getFullYear();
            if (interval[0].getTime() != interval[1].getTime()) {
                toDate = interval[1];
                endDate.innerHTML = (toDate.getMonth() + 1) + "/" + toDate.getDate() + "/" + toDate.getFullYear();
            } else {
                endDate.innerHTML = "";
            }
        }
    }, cal, true);

    cal.render();

    return cal
};

function isDate(y, m, d){ //v1.0
    if(typeof y == "string" && m instanceof RegExp && d){
        if(!m.test(y)) return 1;
        y = RegExp["$" + d.y], m = RegExp["$" + d.m], d = RegExp["$" + d.d];
    }
    d = Math.abs(d) || 0, m = Math.abs(m) || 0, y = Math.abs(y) || 0;
    return arguments.length != 3 ? 1 : d < 1 || d > 31 ? 2 : m < 1 || m > 12 ? 3 : /4|6|9|11/.test(m) && d == 31 ? 4
    : m == 2 && (d > ((y = !(y % 4) && (y % 1e2) || !(y % 4e2)) ? 29 : 28)) ? 5 + !!y : 0;
};



