﻿/**
* Date prototype extensions. Doesn't depend on any
* other code. Doens't overwrite existing methods.
*
* Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
* isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
* setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
*
* @preserve Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
*
* Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
* I've added my name to these methods so you know who to blame if they are broken!
* 
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*
**/

/**
* An Array of day names starting with Sunday.
* 
* @example dayNames[0]
* @result 'Sunday'
*
* @name dayNames
* @type Array
* @cat Plugins/Methods/Date
*/
//Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
Date.dayNames = DayNamesVariable.split(',');
/**
* An Array of abbreviated day names starting with Sun.
* 
* @example abbrDayNames[0]
* @result 'Sun'
*
* @name abbrDayNames
* @type Array
* @cat Plugins/Methods/Date
*/
//Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
Date.abbrDayNames = AbbrDayNamesVariable.split(',');
// Added calendar heading version of abbreviated day names..
if (typeof (AbbrCalDayNamesVariable) != "undefined" && AbbrCalDayNamesVariable != null) {
    Date.abbrCalDayNames = AbbrCalDayNamesVariable.split(',');
} else {
    Date.abbrCalDayNames = Date.abbrDayNames;
}
/**
* An Array of month names starting with Janurary.
* 
* @example monthNames[0]
* @result 'January'
*
* @name monthNames
* @type Array
* @cat Plugins/Methods/Date
*/
//Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
Date.monthNames = MonthNamesVariable.split(',');
/**
* An Array of abbreviated month names starting with Jan.
* 
* @example abbrMonthNames[0]
* @result 'Jan'
*
* @name monthNames
* @type Array
* @cat Plugins/Methods/Date
*/
//Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Date.abbrMonthNames = AbbrMonthNamesVariable.split(',');
/**
* The first day of the week for this locale.
*
* @name firstDayOfWeek
* @type Number
* @cat Plugins/Methods/Date
* @author Kelvin Luck
*/
Date.firstDayOfWeek = FirstDayOfWeekVariable;
//Date.firstDayOfWeek = 0;

/**
* The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
*
* @name format
* @type String
* @cat Plugins/Methods/Date
* @author Kelvin Luck
*/
//Date.format = 'dd/mm/yyyy';
Date.format = ShortDatePatternVariable;
//Date.format = 'mm/dd/yyyy';
//Date.format = 'yyyy-mm-dd';
//Date.format = 'dd mmm yy';

/**
* The first two numbers in the century to be used when decoding a two digit year. Since a two digit year is ambiguous (and date.setYear
* only works with numbers < 99 and so doesn't allow you to set years after 2000) we need to use this to disambiguate the two digit year codes.
*
* @name format
* @type String
* @cat Plugins/Methods/Date
* @author Kelvin Luck
*/
Date.fullYearStart = '20';

(function () {

    /**
    * Adds a given method under the given name 
    * to the Date prototype if it doesn't
    * currently exist.
    *
    * @private
    */
    function add(name, method) {
        if (!Date.prototype[name]) {
            Date.prototype[name] = method;
        }
    };

    /**
    * Checks if the year is a leap year.
    *
    * @example var dtm = new Date("01/12/2008");
    * dtm.isLeapYear();
    * @result true
    *
    * @name isLeapYear
    * @type Boolean
    * @cat Plugins/Methods/Date
    */
    add("isLeapYear", function () {
        var y = this.getFullYear();
        return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    });

    /**
    * Checks if the day is a weekend day (Sat or Sun).
    *
    * @example var dtm = new Date("01/12/2008");
    * dtm.isWeekend();
    * @result false
    *
    * @name isWeekend
    * @type Boolean
    * @cat Plugins/Methods/Date
    */
    add("isWeekend", function () {
        return this.getDay() == 0 || this.getDay() == 6;
    });

    /**
    * Check if the day is a day of the week (Mon-Fri)
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.isWeekDay();
    * @result false
    * 
    * @name isWeekDay
    * @type Boolean
    * @cat Plugins/Methods/Date
    */
    add("isWeekDay", function () {
        return !this.isWeekend();
    });

    /**
    * Gets the number of days in the month.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getDaysInMonth();
    * @result 31
    * 
    * @name getDaysInMonth
    * @type Number
    * @cat Plugins/Methods/Date
    */
    add("getDaysInMonth", function () {
        return [31, (this.isLeapYear() ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][this.getMonth()];
    });

    /**
    * Gets the name of the day.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getDayName();
    * @result 'Saturday'
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getDayName(true);
    * @result 'Sat'
    * 
    * @param abbreviated Boolean When set to true the name will be abbreviated.
    * @name getDayName
    * @type String
    * @cat Plugins/Methods/Date
    */
    add("getDayName", function (abbreviated) {
        return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
    });

    /**
    * Gets the name of the month.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getMonthName();
    * @result 'Janurary'
    *
    * @example var dtm = new Date("01/12/2008");
    * dtm.getMonthName(true);
    * @result 'Jan'
    * 
    * @param abbreviated Boolean When set to true the name will be abbreviated.
    * @name getDayName
    * @type String
    * @cat Plugins/Methods/Date
    */
    add("getMonthName", function (abbreviated) {
        return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
    });

    /**
    * Get the number of the day of the year.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getDayOfYear();
    * @result 11
    * 
    * @name getDayOfYear
    * @type Number
    * @cat Plugins/Methods/Date
    */
    add("getDayOfYear", function () {
        var tmpdtm = new Date("1/1/" + this.getFullYear());
        return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
    });

    /**
    * Get the number of the week of the year.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.getWeekOfYear();
    * @result 2
    * 
    * @name getWeekOfYear
    * @type Number
    * @cat Plugins/Methods/Date
    */
    add("getWeekOfYear", function () {
        return Math.ceil(this.getDayOfYear() / 7);
    });

    /**
    * Set the day of the year.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.setDayOfYear(1);
    * dtm.toString();
    * @result 'Tue Jan 01 2008 00:00:00'
    * 
    * @name setDayOfYear
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("setDayOfYear", function (day) {
        this.setMonth(0);
        this.setDate(day);
        return this;
    });

    /**
    * Add a number of years to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addYears(1);
    * dtm.toString();
    * @result 'Mon Jan 12 2009 00:00:00'
    * 
    * @name addYears
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addYears", function (num) {
        this.setFullYear(this.getFullYear() + num);
        return this;
    });

    /**
    * Add a number of months to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addMonths(1);
    * dtm.toString();
    * @result 'Tue Feb 12 2008 00:00:00'
    * 
    * @name addMonths
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addMonths", function (num) {
        var tmpdtm = this.getDate();

        this.setMonth(this.getMonth() + num);

        if (tmpdtm > this.getDate())
            this.addDays(-this.getDate());

        return this;
    });

    /**
    * Add a number of days to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addDays(1);
    * dtm.toString();
    * @result 'Sun Jan 13 2008 00:00:00'
    * 
    * @name addDays
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addDays", function (num) {
        //this.setDate(this.getDate() + num);
        this.setTime(this.getTime() + (num * 86400000));
        return this;
    });

    /**
    * Add a number of hours to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addHours(24);
    * dtm.toString();
    * @result 'Sun Jan 13 2008 00:00:00'
    * 
    * @name addHours
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addHours", function (num) {
        this.setHours(this.getHours() + num);
        return this;
    });

    /**
    * Add a number of minutes to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addMinutes(60);
    * dtm.toString();
    * @result 'Sat Jan 12 2008 01:00:00'
    * 
    * @name addMinutes
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addMinutes", function (num) {
        this.setMinutes(this.getMinutes() + num);
        return this;
    });

    /**
    * Add a number of seconds to the date object.
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.addSeconds(60);
    * dtm.toString();
    * @result 'Sat Jan 12 2008 00:01:00'
    * 
    * @name addSeconds
    * @type Date
    * @cat Plugins/Methods/Date
    */
    add("addSeconds", function (num) {
        this.setSeconds(this.getSeconds() + num);
        return this;
    });

    /**
    * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
    * 
    * @example var dtm = new Date();
    * dtm.zeroTime();
    * dtm.toString();
    * @result 'Sat Jan 12 2008 00:01:00'
    * 
    * @name zeroTime
    * @type Date
    * @cat Plugins/Methods/Date
    * @author Kelvin Luck
    */
    add("zeroTime", function () {
        this.setMilliseconds(0);
        this.setSeconds(0);
        this.setMinutes(0);
        this.setHours(0);
        return this;
    });

    /**
    * Returns a string representation of the date object according to Date.format.
    * (Date.toString may be used in other places so I purposefully didn't overwrite it)
    * 
    * @example var dtm = new Date("01/12/2008");
    * dtm.asString();
    * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
    * 
    * @name asString
    * @type Date
    * @cat Plugins/Methods/Date
    * @author Kelvin Luck
    */
    add("asString", function (format) {
        var r = format || Date.format;
        return r
			.split('yyyy').join(this.getFullYear())
			.split('yy').join((this.getFullYear() + '').substring(2))
			.split('mmmm').join(this.getMonthName(false))
			.split('mmm').join(this.getMonthName(true))
			.split('mm').join(_zeroPad(this.getMonth() + 1))
			.split('dd').join(_zeroPad(this.getDate()))
			.split('hh').join(_zeroPad(this.getHours()))
			.split('min').join(_zeroPad(this.getMinutes()))
			.split('ss').join(_zeroPad(this.getSeconds()));
    });

    /**
    * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
    * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
    *
    * @example var dtm = Date.fromString("12/01/2008");
    * dtm.toString();
    * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
    * 
    * @name fromString
    * @type Date
    * @cat Plugins/Methods/Date
    * @author Kelvin Luck
    */
    Date.fromString = function (s, format) {
        var f = format || Date.format;
        var d = new Date('01/01/1977');

        var mLength = 0;

        var iM = f.indexOf('mmmm');
        if (iM > -1) {
            for (var i = 0; i < Date.monthNames.length; i++) {
                var mStr = s.substr(iM, Date.monthNames[i].length);
                if (Date.monthNames[i] == mStr) {
                    mLength = Date.monthNames[i].length - 4;
                    break;
                }
            }
            d.setMonth(i);
        } else {
            iM = f.indexOf('mmm');
            if (iM > -1) {
                var mStr = s.substr(iM, 3);
                for (var i = 0; i < Date.abbrMonthNames.length; i++) {
                    if (Date.abbrMonthNames[i] == mStr) break;
                }
                d.setMonth(i);
            } else {
                d.setMonth(Number(s.substr(f.indexOf('mm'), 2)) - 1);
            }
        }

        var iY = f.indexOf('yyyy');

        if (iY > -1) {
            if (iM < iY) {
                iY += mLength;
            }
            d.setFullYear(Number(s.substr(iY, 4)));
        }
        if (iY <= -1) {
            iY = f.indexOf('yy');
            if (iM < iY) {
                iY += mLength;
            }
            var yearString = s.substr(iY, 4);
            if (yearString.length == 2) {
                yearString = '20' + yearString;
            }
            d.setFullYear(Number(yearString));
        }

        if (iY <= -1) {
            if (iM < iY) {
                iY += mLength;
            }
            // TODO - this doesn't work very well - are there any rules for what is meant by a two digit year?
            d.setFullYear(Number(Date.fullYearStart + s.substr(f.indexOf('yy'), 2)));
        }
        var iD = f.indexOf('dd');
        if (iM < iD) {
            iD += mLength;
        }
        d.setDate(Number(s.substr(iD, 2)));
        if (isNaN(d.getTime())) {
            return false;
        }
        return d;
    };

    // utility method
    var _zeroPad = function (num) {
        var s = '0' + num;
        return s.substring(s.length - 2)
        //return ('0'+num).substring(-2); // doesn't work on IE :(
    };

})();


// =====================
// HC Calendar Namespace
// =====================

HC.Calendar = {
    instances: [],
    settings: [],

    bodyElementId: '#hc_bodyElements',
    popupContainerId: '#hc_popupSearch',

    // default calendar settings - override via parameter on calendar plugin init
    defaultSettings: {
        padding: 20,
        mouseOverColor: '#CFF0FF',
        mouseOutColor: '#fff',
        selectedBackgroundColor: '#F7860D',
        otherCalSelectedDateBackgroundColor: '#d3f2fa',
        defaultColor: '#3377DD',
        canNavigateMonthAhead: 12,
        minDate: null,
        maxDate: null,
        selectedDateCalPosition: 0,
        firstDayOfWeek: parseInt(FirstDayOfWeekVariable),
        individualCalSettings: null,
        containerId: '',
        numberOfMonthsToShow: 0,
        calendarContainerstyle: {
            position: 'absolute',
            marginLeft: 0,
            marginTop: 0,
            width: '438px'
        },
        useInbuiltCalendarStyles: true
    },

    // Use SearchBoxUI methods generating javascript calls instead on calling it directly in code 
    init: function (containerId, positionType, options) {
        var calendar1Id = containerId + '_Checkin';
        var calendar2Id = containerId + '_Checkout';
        var checkinDateString = CheckinValueFromCookieVariable == '' ? null : this.formatDate(Date.fromString(CheckinValueFromCookieVariable, DefaultShortDatePatternVariable), ShortDatePatternVariable);
        var checkoutDateString = CheckoutValueFromCookieVariable == '' ? null : this.formatDate(Date.fromString(CheckoutValueFromCookieVariable, DefaultShortDatePatternVariable), ShortDatePatternVariable);

        if (checkinDateString == '' || checkinDateString == null || checkoutDateString == '' || checkoutDateString == null) {
            checkinDateString = '';
            checkoutDateString = '';
        }

        // move calendar and ie6 iframe overlay to be immediate child of body elements..
        var $container = $('#' + containerId);
        $container.appendTo(this.bodyElementId);
        $container.css("top", "0");
        $container.css("left", "0");

        $container.bgIframe();

        options = options || {};
        options = $.extend(
            { calendar1Id: calendar1Id,
                calendar2Id: calendar2Id,
                selectedDate1String: checkinDateString,
                selectedDate2String: checkoutDateString,
                containerId: containerId,
                positionType: positionType,
                numberOfMonthsToShow: 2
            },
            options
        );

        var newCalendar = $container.hcCalendar(options);
        var newCalendarRef = {
            containerId: containerId,
            calendar: newCalendar
        };

        this.instances.push(newCalendarRef);
    },

    inModalContainer: function (obj) {
        if ($(obj).parents(this.popupContainerId).length != 0) {
            return true;
        } else {
            return false;
        }
    },

    rePosition: function () {
        for (i = 0; i < this.instances.length; i++) {
            var $pageCalendar = $('#' + this.instances[i].containerId);

            if (($pageCalendar.length == 1) && $pageCalendar.is(':visible')) {
                var parts = $pageCalendar.children()[0].id.split('-');
                var clendarInputId = parts[0];
                var $clendarInput = $('#' + clendarInputId);

                // get calendar position..
                var pos;

                var $mainWrap = $('#hc_r_content');
                if ($mainWrap.length > 0) {
                    pos = HC.Common.findPopoverPos($clendarInput[0], $pageCalendar, true, false, true, false, false, 0, 0);
                } else {
                    pos = HC.Common.findPos($clendarInput[0]);
                }

                // set calendar position type..
                var calPosType = "absolute";
                if (this.inModalContainer($clendarInput[0]) && (typeof document.body.style.maxHeight != "undefined")) {
                    calPosType = "fixed";
                }

                $pageCalendar.css({
                    top: pos.y,
                    left: pos.x,
                    position: calPosType
                });
                //HC.Design.addUnderlay($pageCalendar);

                break;
            }

        }
    },

    hide: function () {
        for (i = 0; i < this.instances.length; i++) {
            $('#' + this.instances[i].containerId).hide();
            //HC.Design.removeUnderlay();
        }
    },

    selectDate: function (year, month, date, id) {
        var containerId = this.getContainerIdFromInput(id);
        var settings = HC.Calendar.settings[containerId];
        var individualCalSettings = HC.Calendar.settings[containerId].individualCalSettings;
        individualCalSettings[id].selectedDate = new Date(year, month, date);

        $('#' + id).val(this.formatDate(new Date(year, month, date), Date.format, settings.firstDayOfWeek));
        $('#' + id + 'Value').val(this.formatDate(individualCalSettings[id].selectedDate, Date.format, settings.firstDayOfWeek));
        $('#' + id + 'Format').html(this.formatDate(individualCalSettings[id].selectedDate, LongDatePatternVariable, settings.firstDayOfWeek));

        if (id == settings.calendar1Id) {
            if (individualCalSettings[settings.calendar2Id].selectedDate != null && individualCalSettings[settings.calendar1Id].selectedDate > individualCalSettings[settings.calendar2Id].selectedDate) {
                $('#' + settings.calendar2Id).val('');
                $('#' + settings.calendar2Id + 'Value').val('');
                individualCalSettings[settings.calendar2Id].selectedDate = null;
                $('#' + settings.calendar2Id + 'Format').html(ShortDatePatternVariable);
            }
        }
        else if (id == settings.calendar2Id) {
            if (individualCalSettings[settings.calendar1Id].selectedDate != null && individualCalSettings[settings.calendar2Id].selectedDate < individualCalSettings[settings.calendar1Id].selectedDate) {
                $('#' + settings.calendar1Id).val('');
                $('#' + settings.calendar1Id + 'Value').val('');
                individualCalSettings[settings.calendar1Id].selectedDate = null;
                $('#' + settings.calendar1Id + 'Format').html(ShortDatePatternVariable);
            }
        }

        this.hide();
    },

    build: function (id, month, year, monthElClass, headerClass, dayNamesClass, daysClass, border, pos, containerId) {
        var dim = [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
        var settings = HC.Calendar.settings[this.getContainerIdFromInput(id)];
        var individualCalSettings = HC.Calendar.settings[this.getContainerIdFromInput(id)].individualCalSettings;
        var oD = new Date(year, month - 1, 1);
        var oDMax = new Date(year, month, 1);
        oD.od = oD.getDay() + 1;
        var canNavigateBack = oD > settings.minDate;
        var canNavigateForward = oDMax < settings.maxDate;
        var todayDate = new Date();
        var scanForToday = (year == todayDate.getFullYear() && month == todayDate.getMonth() + 1) ? todayDate.getDate() : 0;
        var scanForSelectedDate = (individualCalSettings[id].selectedDate != null && year == individualCalSettings[id].selectedDate.getFullYear() && month == individualCalSettings[id].selectedDate.getMonth() + 1) ? individualCalSettings[id].selectedDate.getDate() : 0;
        var scanForCheckinSelectedDate = null;

        if (individualCalSettings[id].id == settings.calendar2Id) {
            //this is second calendar. make sure you highlight first calendar selected date in it
            scanForCheckinSelectedDate = (individualCalSettings[settings.calendar1Id].selectedDate != null && year == individualCalSettings[settings.calendar1Id].selectedDate.getFullYear() && month == individualCalSettings[settings.calendar1Id].selectedDate.getMonth() + 1) ? individualCalSettings[settings.calendar1Id].selectedDate.getDate() : null;
        }

        var canNavigateBackwardLink = (pos == 0 && canNavigateBack ? '<a href="#" id="' + id + '-prev" onclick="return false;" onmouseup="HC.Calendar.prevMonth(this, event);event.returnValue = false;return false;" class="navPrev">«</a>' : pos == 0 ? '<a href="#" id="' + id + '-prev"  class="navPrev disabled">«</a>' : '');
        var navigateForwardLink = '';

        if (pos == (settings.numberOfMonthsToShow - 1)) {
            navigateForwardLink = '<a href="#"  onclick="return false;"  onmouseup="HC.Calendar.hide()" id="' + id + 'Close" class="closeCalendar">x</a>';
        }

        navigateForwardLink += (pos == (settings.numberOfMonthsToShow - 1) && canNavigateForward ? '<a href="#" id="' + id + '-next" onclick="return false;"  onmouseup="HC.Calendar.nextMonth(this, event);event.returnValue = false;return false;" class="navNext">»</a>' : pos == (settings.numberOfMonthsToShow - 1) ? '<a href="#" id="' + id + '-next"  class="navNext disabled">«</a>' : '');

        dim[1] = (((oD.getFullYear() % 100 != 0) && (oD.getFullYear() % 4 == 0)) || (oD.getFullYear() % 400 == 0)) ? 29 : 28;

        var t = '<div id="' + id + '-' + ((month - 1) + '-' + year + '-HcCalendar') + '-' + pos + '-' + containerId + '" class="' + monthElClass + '"><table class="' + monthElClass + '" cols="7" cellpadding="0" border="' + border + '" cellspacing="0"><tr align="center">';
        t += '<td class="' + headerClass + '">' + canNavigateBackwardLink + '</td><td colspan="4" align="center" class="' + headerClass + '">' + Date.monthNames[month - 1] + ' - ' + year + '</td><td colspan="2" class="' + headerClass + '">' + navigateForwardLink + '</td></tr><tr align="center">';

        var firstDayOfWeek = settings.firstDayOfWeek;
        for (s = 0; s < 7; s++) {
            var dayIndex = s;
            if (firstDayOfWeek > 0) {
                dayIndex = (s + firstDayOfWeek) > 6 ? (s + firstDayOfWeek) - 7 : (s + firstDayOfWeek);
            }
            t += '<td class="' + dayNamesClass + '" title="' + Date.dayNames[dayIndex] + '">' + Date.abbrCalDayNames[dayIndex] + '</td>';
        }

        t += '</tr><tr align="center">';

        var lowerIndex = 1 + firstDayOfWeek;
        var upperIndex = 42 + firstDayOfWeek;
        for (i = lowerIndex; i <= upperIndex; i++) {
            var dayIndex = i;

            if (firstDayOfWeek > 0) {
                dayIndex = i > upperIndex ? i - upperIndex : i;
            }

            var startDayIndex = oD.od - firstDayOfWeek < firstDayOfWeek ? oD.od + 7 : oD.od;
            var x = ((dayIndex - startDayIndex >= 0) && (dayIndex - startDayIndex < dim[month - 1])) ? dayIndex - startDayIndex + 1 : '&nbsp;';
            var empty = x == '&nbsp;';
            var cellDate = new Date(year, month - 1, x);
            var cellClickable = (empty || settings.minDate > cellDate || settings.maxDate < cellDate ? '' : ' onmouseup="HC.Calendar.dayClick(this)" onmouseover="HC.Calendar.dayOver(this)" onmouseout="HC.Calendar.dayOut(this)"');

            if (empty) {
                daysClass = 'empty';
            }
            else {
                daysClass = 'days';
            }

            // disable date cell (outside bounds)
            if ((settings.minDate > cellDate) || (settings.maxDate < cellDate)) {
                if (x != scanForCheckinSelectedDate) {
                    daysClass += ' disabled';
                }
            }

            if (x == scanForToday) {
                daysClass += ' today';
            }

            if (x == scanForSelectedDate) {
                daysClass += ' selected';
            }

            if (x == scanForCheckinSelectedDate) {
                daysClass += ' otherCalDate';
            }

            t += '<td class="' + daysClass + '" ' + cellClickable + '>' + x + '</td>';

            if (((i - firstDayOfWeek) % 7 == 0) && (i - firstDayOfWeek < 36)) t += '</tr><tr align="center">';
        }
        return t += '</tr></table></div>';
    },

    update: function (inputId, theMonth, theYear) {
        var containerId = this.getContainerIdFromInput(inputId);
        var settings = this.settings[containerId];
        var calendarHTML1 = HC.Calendar.build(inputId, theMonth, theYear, "hc_main", "month", "daysofweek", "days", 0, 0);

        if (++theMonth == 13) {
            theMonth = 1;
            theYear++;
        }

        // Update HTML
        if (settings.numberOfMonthsToShow > 1) {
            var calendarHTML2 = HC.Calendar.build(inputId, theMonth, theYear, "hc_main", "month", "daysofweek", "days", 0, 1);
            $('#' + containerId)[0].innerHTML = (calendarHTML1 + calendarHTML2);
        }
        else {
            $('#' + containerId)[0].innerHTML = (calendarHTML1);
        }
        //HC.Design.addUnderlay($('#' + containerId));
        $('#' + containerId).bgIframe();
    },

    show: function (inputId, e) {
        var containerId = this.getContainerIdFromInput(inputId);
        var settings = this.settings[containerId];
        var individualCalSettings = this.settings[containerId].individualCalSettings;
        var $input = $('#' + inputId);

        // first hide any existing open calendars..
        HC.Calendar.hide();

        var calPosition = 0;
        var noSelection = false;
        var dateToDisplay = individualCalSettings[inputId].selectedDate;
        if (dateToDisplay == null) {
            if (inputId == settings.calendar1Id) {
                dateToDisplay = individualCalSettings[settings.calendar2Id].selectedDate;
            }
            else {
                dateToDisplay = individualCalSettings[settings.calendar1Id].selectedDate;
            }

            if (dateToDisplay == null) {
                dateToDisplay = new Date();
                noSelection = true;
            }
        }

        var theMonth = individualCalSettings[inputId].currentMonth = dateToDisplay.getMonth() + 1;
        var theYear = individualCalSettings[inputId].currentYear = dateToDisplay.getFullYear();
        //this calendar has no selectd date suggest display month from other calendar
        if ($input.val() == '' && !noSelection) {
            if (settings.selectedDateCalPosition == 1) {
                if (--theMonth == 0) {
                    theMonth = 12;
                    theYear--;
                }
            }
        }

        var calendarHTML1 = HC.Calendar.build(inputId, theMonth, theYear, "hc_main", "month", "daysofweek", "days", 0, calPosition++);
        if (++theMonth == 13) {
            theMonth = 1;
            theYear++;
        }

        //The next month calendar builder
        if (settings.numberOfMonthsToShow > 1) {
            var calendarHTML2 = HC.Calendar.build(inputId, theMonth, theYear, "hc_main", "month", "daysofweek", "days", 0, calPosition);
        }

        var containerStyle = '';
        var $calendarContainer = $('#' + containerId);

        if (inputId == settings.calendar1Id) {
            $calendarContainer.addClass("hc_cal_checkin");
        }
        else if (inputId == settings.calendar2Id) {
            $calendarContainer.addClass("hc_cal_checkout");
        }

        if ($calendarContainer.length == 1) {
            if (settings.numberOfMonthsToShow > 1) {
                $calendarContainer.html(calendarHTML1 + calendarHTML2);
            }
            else {
                $calendarContainer.html(calendarHTML1);
            }

            // IE6, older browsers
            if (typeof document.body.style.maxHeight == "undefined") {
                //$calendarContainer.css("width", "440px");
            }

            // Change position type for modals
            if (HC.Calendar.inModalContainer($input[0]) && (typeof document.body.style.maxHeight != "undefined")) {
                settings.calendarContainerstyle.position = "fixed";
            }

            var pos;

            var $mainWrap = $('#hc_r_content');
            if ($mainWrap.length > 0) {
                pos = HC.Common.findPopoverPos($input[0], $calendarContainer[0], true, false, true, false, false, 0, 0);
            } else {
                pos = HC.Common.findPos($input[0]);
            }

            // position the calender on page
            if (settings.useInbuiltCalendarStyles) {
                $calendarContainer.css({
                    position: settings.calendarContainerstyle.position,
                    top: pos.y,
                    left: pos.x,
                    width: settings.calendarContainerstyle.width
                });
            } else {
                $calendarContainer.css({
                    position: settings.calendarContainerstyle.position,
                    top: pos.y,
                    left: pos.x
                });
            }
            $calendarContainer.show();
            $calendarContainer.bgIframe();
            //HC.Design.addUnderlay($calendarContainer);
        }
    },

    dayClick: function (el) {
        var parameters = el.parentNode.parentNode.parentNode.parentNode.id.split('-'); ;
        var date = el.innerHTML;
        var containerId = this.getContainerIdFromInput(parameters[0]);
        var settings = HC.Calendar.settings[containerId];

        // store selected date calendar position in settings
        settings.selectedDateCalPosition = parameters[4];
        HC.Calendar.selectDate(parameters[2], parameters[1], date, parameters[0]);
    },

    dayOver: function (el) {
        var parameters = el.parentNode.parentNode.parentNode.parentNode.id.split('-');
        var containerId = this.getContainerIdFromInput(parameters[0]);
        var settings = HC.Calendar.settings[containerId];

        el.style.backgroundColor = settings.mouseOverColor;
        el.style.color = '#000';
    },

    dayOut: function (el) {
        var parameters = el.parentNode.parentNode.parentNode.parentNode.id.split('-'); ;
        var containerId = this.getContainerIdFromInput(parameters[0]);
        var settings = HC.Calendar.settings[containerId];

        if (el.className.indexOf('selected') != -1) {
            el.style.backgroundColor = settings.selectedBackgroundColor;
            el.style.color = '#fff';
        }
        else if (el.className.indexOf('today') != -1) {
            el.style.backgroundColor = settings.mouseOutColor;
            el.style.color = '#000';
        }
        else if (el.className.indexOf('otherCalDate') != -1) {
            el.style.backgroundColor = settings.otherCalSelectedDateBackgroundColor;
            el.style.color = settings.defaultColor;
        }
        else {
            el.style.backgroundColor = settings.mouseOutColor;
            el.style.color = settings.defaultColor;
        }
    },

    prevMonth: function (el, e) {
        var containerId = this.getContainerIdFromInput(el.id);
        var settings = HC.Calendar.settings[containerId];
        var individualCalSettings = HC.Calendar.settings[containerId].individualCalSettings;
        var parameters = el.id.split('-');

        //individualCalSettings[parameters[0]].currentMonth;
        if (--individualCalSettings[parameters[0]].currentMonth == 0) {
            individualCalSettings[parameters[0]].currentMonth = 12;
            individualCalSettings[parameters[0]].currentYear--;
        }

        this.update(parameters[0], individualCalSettings[parameters[0]].currentMonth, individualCalSettings[parameters[0]].currentYear);
    },

    nextMonth: function (el, e) {
        var containerId = this.getContainerIdFromInput(el.id);
        var settings = HC.Calendar.settings[containerId];
        var individualCalSettings = HC.Calendar.settings[containerId].individualCalSettings;
        var parameters = el.id.split('-');

        if (++individualCalSettings[parameters[0]].currentMonth == 13) {
            individualCalSettings[parameters[0]].currentMonth = 1;
            individualCalSettings[parameters[0]].currentYear++;
        }

        this.update(parameters[0], individualCalSettings[parameters[0]].currentMonth, individualCalSettings[parameters[0]].currentYear);
    },

    getContainerIdFromInput: function (inputId) {
        var inputIdParts = inputId.split('_');
        return inputIdParts[0];
    },

    LZ: function (x) {
        return (x < 0 || x > 9 ? "" : "0") + x;
    },

    formatDate: function (date, format) {
        // formatDate (date_object, format)
        // Returns a date in the output format specified.
        // The format string uses the same abbreviations as in getDateFromFormat()

        format = format + "";
        var result = "";
        var i_format = 0;
        var c = "";
        var token = "";
        var y = date.getFullYear() + "";
        var M = date.getMonth();
        var dw = date.getDay();
        dw = dw > 6 ? dw - 7 : dw;
        var d = date.getDate();
        var yyyy, yy, MMM, MM, dd;
        // Convert real date parts into formatted versions
        var value = new Object();
        if (y.length < 4) { y = "" + (y - 0 + 1900); }
        value["y"] = "" + y;
        value["yyyy"] = y;
        //value["yy"] = y.substring(2,4);
        value["yy"] = y;
        value["M"] = M + 1;
        value["MM"] = this.LZ(M + 1);
        value["MMM"] = Date.abbrMonthNames[M];
        value["MMMM"] = Date.monthNames[M];
        value["m"] = M + 1;
        value["mm"] = this.LZ(M + 1);
        value["mmm"] = Date.abbrMonthNames[M];
        value["mmmm"] = Date.monthNames[M];
        value["NNN"] = Date.monthNames[M + 11];
        value["d"] = d;
        value["dd"] = this.LZ(d);
        value["ddd"] = Date.abbrDayNames[dw];
        value["dddd"] = Date.dayNames[dw];

        while (i_format < format.length) {
            c = format.charAt(i_format);
            token = "";
            while ((format.charAt(i_format) == c) && (i_format < format.length)) {
                token += format.charAt(i_format++);
            }
            if (value[token] != null) {
                result = result + value[token];
            }
            else {
                result = result + token;
            }
        }
        return result;
    }
};


// ==================
// HC Calendar Plugin
// ==================

(function ($) {
    var MyHcCalendar = function (element, options) {
        element = $(element);
        
        var todaydate = new Date();
        var sourceElementId = element[0].id;

        // Merge options with defaults and convert strings to dates
        HC.Calendar.settings[sourceElementId] = $.extend(true, {}, HC.Calendar.defaultSettings, options);
        HC.Calendar.settings[sourceElementId].containerId = sourceElementId;
		
        var settings = HC.Calendar.settings[sourceElementId];
        if (settings.positionType == null || settings.positionType == '') {
            settings.positionType = 'absolute';
        }
        
        // settings are used to store calendar properties.individualCalSettings
        // speciific to individual calendar properties e.g. cheching and checkout calendars
        settings.individualCalSettings = new Array();
        var individualCalSettings = settings.individualCalSettings;
		
		// Dates from cookies
        var dateCookiesExist = false;
        if (HC.Common.Cookies.getCookie("checkin") != '' && HC.Common.Cookies.getCookie("checkout") != '') {
            dateCookiesExist = true;
        }
        
        // calendar 1 - checkin value
        var $calendar1IdVal = $("#" + settings.calendar1Id + "Value").val();
        if (dateCookiesExist && $calendar1IdVal != '') {
            settings.selectedDate1String = $calendar1IdVal;
        }

		// calendar 1 - set date into settings
        var selectedDate1 = (settings.selectedDate1String == null || settings.selectedDate1String == '' || SearchBoxPrepopulatedVariable == "0" ? null : Date.fromString(settings.selectedDate1String, Date.format));
        individualCalSettings[settings.calendar1Id] = {
            selectedDateCalPosition: 0,
            selectedDate: selectedDate1,
            currentMonth: selectedDate1 == null ? 0 : selectedDate1.getMonth(),
            currentYear: selectedDate1 == null ? 0 : selectedDate1.getFullYear(),
            id: settings.calendar1Id
        };

        // calendar 2 - checkout value
        var $calendar2IdVal = $("#" + settings.calendar2Id + "Value").val();
        if (dateCookiesExist && $calendar2IdVal != '') {
            settings.selectedDate2String = $calendar2IdVal;
        }

		// calendar 1 - set date into settings
        var selectedDate2 = (settings.selectedDate2String == null || settings.selectedDate2String == '' || SearchBoxPrepopulatedVariable == "0" ? null : Date.fromString(settings.selectedDate2String, Date.format));
        individualCalSettings[settings.calendar2Id] = {
            selectedDateCalPosition: 0,
            selectedDate: selectedDate2,
            currentMonth: selectedDate2 == null ? 0 : selectedDate2.getMonth(),
            currentYear: selectedDate2 == null ? 0 : selectedDate2.getFullYear(),
            id: settings.calendar2Id
        };

        // eliminate time segment in date
        var minDate = todaydate.addDays(-1);
        settings.minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
        settings.maxDate = new Date(settings.minDate.getFullYear() + 1, settings.minDate.getMonth(), settings.minDate.getDate());

        // Calendar 1
        var $calendar1 = $('#' + settings.calendar1Id);
        if (individualCalSettings[settings.calendar1Id].selectedDate != null) {
            $calendar1.val(HC.Calendar.formatDate(individualCalSettings[settings.calendar1Id].selectedDate, Date.format));
        }
        else {
            if ($calendar1.val() == '') {
                $calendar1.val('');
            }
        }

        // Calendar 2
        var $calendar2 = $('#' + settings.calendar2Id);
        if (individualCalSettings[settings.calendar2Id].selectedDate != null) {
            $calendar2.val(HC.Calendar.formatDate(individualCalSettings[settings.calendar2Id].selectedDate, Date.format));
        }
        else {
            if ($calendar2.val() == '') {
                $calendar2.val('');
            }
        }
        
        if (SearchBoxPrepopulatedVariable == "0") {
            $('#' + settings.containerId + '_Guests')[0].selectedIndex = 0;
            $('#' + settings.containerId + '_Rooms')[0].selectedIndex = 0;
        }
        
        // Calendar 1
        var $calendar1format = $("#" + settings.calendar1Id + "Format");
        if (individualCalSettings[settings.calendar1Id].selectedDate == '' ||
            individualCalSettings[settings.calendar1Id].selectedDate == null) { 
            $calendar1format.html(TranslatedShortDatePatternVariable);
        }
        else {
            $calendar1format.html(HC.Calendar.formatDate(individualCalSettings[settings.calendar1Id].selectedDate, LongDatePatternVariable));
        }

        // Calendar 2
        var $calendar2format = $("#" + settings.calendar2Id + "Format");
        if (individualCalSettings[settings.calendar2Id].selectedDate == '' ||
            individualCalSettings[settings.calendar2Id].selectedDate == null) {
            $calendar2format.html(TranslatedShortDatePatternVariable);
        }
        else {
            $calendar2format.html(HC.Calendar.formatDate(individualCalSettings[settings.calendar2Id].selectedDate, LongDatePatternVariable));
        }

		// Bind calender trigger to element clicks
        $('#' + settings.calendar1Id + 'Image').click(function (e) {
            var inputId = this.id.replace('Image', '');
            HC.Calendar.show(inputId, e);
        });
		
        $('#' + settings.calendar2Id + 'Image').click(function (e) {
            var inputId = this.id.replace('Image', '');
            HC.Calendar.show(inputId, e);
        });

        $('#' + settings.calendar1Id).click(function (e) {
            HC.Calendar.show(this.id, e);
        });
		
        $('#' + settings.calendar2Id).click(function (e) {
            HC.Calendar.show(this.id, e);
        });
	};
		
    $.fn.hcCalendar = function (options) {
        return this.each(function () {
            var element = $(this);

            // Return early if this element already has a plugin instance
            if (element.data('myhccalendar')) {
				return;
			}

            var myHcCalendar = new MyHcCalendar(this, options);

            // Store plugin object in this element's data
            element.data('myhccalendar', myHcCalendar);
        });
    };
})(jQuery);


// ========================
// Window & Document Events
// ========================

$(window).resize(function () {
    HC.Calendar.rePosition();
});

$(window).scroll(function () {
    HC.Calendar.rePosition();
});

$(document).click(function (e) {
    // hides all calendars if clicked outside region 
    
    var targetId = e.target.id;
	if (targetId.indexOf('searchBox') != -1) {
        return false;
    }

    var inspectElement = e.target.parentNode;
    do {
		if (inspectElement.id != null && (inspectElement.id.indexOf('searchBox') != -1)) {
            return false;
        }
        inspectElement = inspectElement.parentNode;
    } while (inspectElement != null);
    
    HC.Calendar.hide();
});
