var today = new Date();

var today = new Date(today.getFullYear(), today.getMonth(), today.getDate());

function dayofyear(d) {   // d is a Date object
	var yn = d.getFullYear();
	var mn = d.getMonth();
	var dn = d.getDate();
	var d1 = new Date(yn,0,1,12,0,0); // noon on Jan. 1
	var d2 = new Date(yn,mn,dn,12,0,0); // noon on input date
	var ddiff = Math.round((d2-d1)/864e5);
	
	d1 = null;
	d2 = null;
	ddiff = null;
	dn = null;
	mn = null;
	yn = null;
	
	return ddiff+1;
}

//Utility classes
var DateUtils = {
	//utility methods
	isDateInRange: function (nowDate, startDate, endDate) {
		return DateUtils.compareDates(startDate, nowDate) <= 0 && DateUtils.compareDates(endDate, nowDate) >= 0;
	},

	compareDates: function(date1, date2) {
		var time1  = date1.getTime();
		var time2 = date2.getTime();
		if (time1 > time2) {
			return 1;
		} else {
			if (time1 < time2) {
				return -1;
			} else {
				return 0;
			}
		}
		time1 = null;
		time2 = null;
	},

	daysInMonth: function (year, month) {
		return 32 - new Date(year, month, 32).getDate();
	}
};


var CallbackWrapper = Class.create ({
	data: null,
	callbackFunction: null,
	callbackScope: null,
	initialize: function (data, callback, scope) {
		this.callbackFunction = callback;
		this.data = data;
		this.callbackScope = scope;
	},
	callbackWrapper: function () {
		this.callbackFunction.call(this.callbackScope, this.data);
	}
});

var SingleMonthCalendar = Class.create ({

	//HTML Templates
	calendarTableTemplate: "<table cellspacing=\"0\" cellpadding=\"0\" summary=\"\" class=\"calTable\" id=\"calendar{calendarId}\"><thead><tr><th id=\"calendar{calendarId}Header\" class=\"calendarTitleHeader\" colspan=\"7\"><div id=\"calendar{calendarId}NextMonthSelector\" class=\"nextMonthSelector\"></div><div id=\"calendar{calendarId}PreviousMonthSelector\" class=\"previousMonthSelector\"></div><span id=\"calendar{calendarId}HeaderTitle\" class=\"calendarTitle\">{calendarHeaderTitle}</span></th></tr><tr class=\"dayNames\"><th title=\"\">{sunday}</th><th title=\"\">{monday}</th><th title=\"\">{tuesday}</th><th title=\"\">{wednesday}</th><th title=\"\">{thursday}</th><th title=\"\">{friday}</th><th title=\"\">{saturday}</th></tr></thead><tbody id=\"calendar{calendarId}Body\">{calendarBody}</tbody></table>",
			
	emptyDayTemplate: "<td class=\"emptyDay {dayClasses}\"> </td>",
	
	dayTemplate: "<td class=\"monthDay {dayClasses}\" id=\"calendar{calendarId}Day{day}Column\"><div id=\"calendar{calendarId}Day{day}Area\" class=\"dayNumber\"><a id=\"calendar{calendarId}Day{day}Ref\" href=\"javascript: ;\">{day}</a></div></td>",
	
	//global variables
	onlyFutureDates: false,
	baseDate: today,
	parentTag: document,
	calendarId: Math.random(),
	
	nextMonthSelectorFn: null,
	nextMonthSelectorFnScope: this,
	previousMonthSelectorFn: null,
	previousMonthSelectorFnScope: this,
	
	onmouseOverFn: null,
	onmouseOverFnScope: this,
	selectCallback: null,
	selectCallbackScope: this,
	
	//Initialization
	initialize: function (parentTag, calendarId, onlyFutureDates) {
				
		if(parentTag !== null) {
			this.parentTag = parentTag;
		}
		
		if(id !== null) {
			this.calendarId = calendarId;
		}

		this.calendarTableTemplate = new Ext.Template(this.calendarTableTemplate);
		this.emptyDayTemplate = new Ext.Template(this.emptyDayTemplate);
		this.dayTemplate = new Ext.Template(this.dayTemplate);
		this.nextMonthSelectorFn = this.moveToNextMonth;
		this.nextMonthSelectorFnScope = this;
		this.previousMonthSelectorFn = this.moveToPreviousMonth;
		this.previousMonthSelectorFnScope = this;
		if(onlyFutureDates !== null) {
			this.onlyFutureDates = onlyFutureDates;
		}
	},

	//Callbacks initialization
	setOnSelectCallback: function (callbackFn, scope) {
		this.selectCallback = callbackFn;
		if(scope !== null) {
			this.selectCallbackScope = scope;
		}
	},
	
	
	setOnMouseOverCallback: function (callbackFn, scope) {
		this.onmouseOverFn = callbackFn;
		if(scope !== null) {
			this.onmouseOverFnScope = scope;
		}
	},


	setOnSelectPreviousMonthCallback: function (callbackFn, scope) {
		this.previousMonthSelectorFn = callbackFn;
		if(scope !== null) {
			this.previousMonthSelectorFnScope = scope;
		}
	},
	setOnSelectNextMonthCallback: function (callbackFn, scope) {
		this.nextMonthSelectorFn = callbackFn;
		if(scope !== null) {
			this.nextMonthSelectorFnScope = scope;
		}
	},
	
	clickOnDateCallback: function (date) {
		if(this.onlyFutureDates && DateUtils.compareDates(date, today) < 0) {
			return;
		}
		this.selectCallback.call(this.selectCallbackScope, date);
	},
	
	//Function to render the calendar if the date is passed it will use to render the respectively month of the given date
	render:	function (date) {

		if(date != null) {
			this.baseDate = date;
		}

		var monthDays = DateUtils.daysInMonth(this.baseDate.getFullYear(), this.baseDate.getMonth());
		var fromDate = new Date(this.baseDate.getFullYear(), this.baseDate.getMonth(), 1);
		var toDate = new Date(this.baseDate.getFullYear(), this.baseDate.getMonth(), monthDays);
		var htmlBuffer = '<tr>';

		var day = null;

		//The range of dates start at the first date of the week regardless if it's within the month or not
		var rangeStarts = fromDate;
		if(rangeStarts.format('w') !== 0) {
			rangeStarts = new Date(fromDate.getTime() - (1000*60*60*24*fromDate.format('w')));
		}

		//The range of dates ends at the last date of the week regardless if it's within the month or not
		var rangeEnds = toDate;
		if(rangeEnds.format('w') != 7) {
			rangeEnds = new Date(toDate.getTime() + (1000*60*60*24*(6 - toDate.format('w'))));
		}
		var iteratingDate = rangeStarts;
		while(DateUtils.isDateInRange(iteratingDate, rangeStarts, rangeEnds)) {
			var dayClasses = "";
			var dayOfWeek = iteratingDate.format('w');

			if(!DateUtils.isDateInRange(iteratingDate, fromDate, toDate)) {
				if(dayOfWeek == 6) {
					dayClasses += "last ";
				}
				if(this.onlyFutureDates && DateUtils.compareDates(iteratingDate, today) < 0) {
					dayClasses += "blank ";
				}
				htmlBuffer += this.emptyDayTemplate.apply({dayClasses: dayClasses});
			} else {
				if(DateUtils.compareDates(iteratingDate, this.baseDate) === 0) {
					dayClasses += "baseDate ";
				}
				if(DateUtils.compareDates(iteratingDate, today) === 0) {
					dayClasses += "today ";
				}
				if(dayOfWeek == 6) {
					dayClasses += "last ";
				}
				if(this.onlyFutureDates && DateUtils.compareDates(iteratingDate, today) < 0) {
					dayClasses += "blank ";
				}
				day = iteratingDate.format('j');
				var dayTemplateValues = { day: day, calendarId: this.calendarId, dayClasses: dayClasses};
				htmlBuffer += this.dayTemplate.apply(dayTemplateValues);
				
				dayTemplateValues = null;
			}

			//Checking if the row needs to be closed
			if(dayOfWeek == 6) {
				htmlBuffer += '</tr>';
				if(DateUtils.compareDates(iteratingDate, rangeEnds) < 0) {
					htmlBuffer += '<tr>';
				}
			}
			iteratingDate = iteratingDate.add(Date.DAY, 1);

			dayClasses = null;
			dayOfWeek = null;
		}

		var sunday = rangeStarts.format('D').substring(0, 1);
		var monday = iteratingDate.add(Date.DAY, 1).format('D').substring(0, 1);
		var tuesday = iteratingDate.add(Date.DAY, 2).format('D').substring(0, 1);
		var wednesday = iteratingDate.add(Date.DAY, 3).format('D').substring(0, 1);
		var thursday = iteratingDate.add(Date.DAY, 4).format('D').substring(0, 1);
		var friday = iteratingDate.add(Date.DAY, 5).format('D').substring(0, 1);
		var saturday = iteratingDate.add(Date.DAY, 6).format('D').substring(0, 1);

		var calendarTableTemplateValues = { calendarHeaderTitle: this.baseDate.format('F, Y'), calendarBody: htmlBuffer, calendarId: this.calendarId,
			 sunday: sunday, monday: monday, tuesday: tuesday, wednesday: wednesday, thursday: thursday, friday: friday,
			 saturday: saturday };
		var html = this.calendarTableTemplate.apply(calendarTableTemplateValues);

		if(this.parentTag === null || this.parentTag == document) {
			Ext.getBody().insertHtml('beforeEnd', html);
		} else {
			Ext.get(this.parentTag).update(html);
		}

		//Hooking up the day events on click
		iteratingDate = fromDate;
		var dayOfYear = dayofyear(today);
		var currentYear = today.getFullYear();
		while(DateUtils.isDateInRange(iteratingDate, fromDate, toDate)) {
			day = iteratingDate.format('j');
			var theDate = new Date(fromDate.getFullYear(), (fromDate.getMonth()), parseInt(day, 10)); 

			if(this.selectCallback !== null) {
				var callbackObj = new CallbackWrapper (theDate, this.clickOnDateCallback, this);
				Ext.get("calendar" + this.calendarId + "Day" + day + "Ref").on('click', callbackObj.callbackWrapper, callbackObj);
				if(dayOfYear > dayofyear(theDate) && currentYear >= theDate.getFullYear()) {
					jQuery("#calendar" + this.calendarId + "Day" + day + "Ref").addClass('previousDate');
				}
				callbackObj = null;
			}

			if(this.onmouseOverFn !== null) {
				var callbackObj2 = new CallbackWrapper ({ date: theDate, calendarId: this.calendarId, columnId: "calendar" + this.calendarId + "Day" + day + "Column" }, 
				this.onmouseOverFn, this.onmouseOverFnScope);
				Ext.get("calendar" + this.calendarId + "Day" + day + "Ref").on('mouseover', callbackObj2.callbackWrapper, callbackObj2);
				callbackObj2 = null;
			}

			theDate.setFullYear(fromDate.getFullYear(), (fromDate.getMonth()), parseInt(day, 10));
			iteratingDate = iteratingDate.add(Date.DAY, 1);
			
			theDate = null;
		}

		 //hooking up the next and previous month selector events
		 if(this.nextMonthSelectorFn !== null) {
			 Ext.get("calendar" + this.calendarId + "NextMonthSelector").on('click', this.nextMonthSelectorFn, this.nextMonthSelectorFnScope, { stopEvent: true });
		 } else {
			 Ext.get("calendar" + this.calendarId + "NextMonthSelector").hide();
		 }
		 if(this.previousMonthSelectorFn !== null) {
			 Ext.get("calendar" + this.calendarId + "PreviousMonthSelector").on('click', this.previousMonthSelectorFn, this.previousMonthSelectorFnScope, { stopEvent: true });
		 } else {
			 Ext.get("calendar" + this.calendarId + "PreviousMonthSelector").hide();
		 }

		calendarTableTemplateValues = null;
		currentYear = null;
		day = null;
		dayOfYear = null;
		friday = null;
		fromDate = null;
		html = null;
		htmlBuffer = null;
		iteratingDate = null;
		monday = null;
		monthDays = null;
		rangeEnds = null;
		rangeStarts = null;
		saturday = null;
		sunday = null;
		thursday = null;
		toDate = null;
		tuesday = null;
		wednesday = null;
	},

	//Default actions
	moveToPreviousMonth: function () {
		this.baseDate = this.baseDate.add(Date.MONTH, -1);
		this.render();
	},
	
	moveToNextMonth: function () {
		this.baseDate = this.baseDate.add(Date.MONTH, 1);
		this.render();
	}


	
});

var SingleMonthPopupCalendar = Class.create ( {
	
	calendarHolderTemplate: '<div id="calendarPopUp{calendarId}" style="display: none; position: absolute;"></div>',
	
	format: 'n/j/Y',
	calendar: null,
	updateTextField: null,
	hideCalendarEventFn: null,
	
	initialize: function (trigger, calendarId, updateTextField, format, onlyFutureDates) {
	
		this.calendarHolderTemplate = new Ext.Template(this.calendarHolderTemplate);
		this.calendarHolderTemplate.append(Ext.getBody(), { calendarId: calendarId });
		
		this.calendarId = calendarId;
		this.updateTextField = updateTextField;
		if(format !== null) {
			this.format = format;
		}
		if(onlyFutureDates) {
			this.calendar = new SingleMonthCalendar('calendarPopUp' + this.calendarId, calendarId, true);
		} else {
			this.calendar = new SingleMonthCalendar('calendarPopUp' + this.calendarId, calendarId, false);
		}
		
		this.calendar.setOnSelectCallback(this.onSelect, this);
		
		
		Ext.get(trigger).on('click', this.showCalendar, this, { stopEvent: true });
		Ext.get(calendarId).on('click', this.showCalendar, this, { stopEvent: true});
		
		this.hideCalendarEventFn = function (event) {
			if(!event.within(Ext.get('calendarPopUp' + this.calendarId))) {
				var popup = Ext.get('calendarPopUp' + this.calendarId);
				popup.setVisibilityMode(Ext.Element.DISPLAY).hide();
			}
		};
		
		Ext.getBody().on('click', this.hideCalendarEventFn, this, { delay: 0 });
		
	},
	
	
	showCalendar: function (event) {
		var currentDate = null;
		
		if(Ext.get(this.updateTextField).dom.value != '') {
			currentDate = Date.parseDate(Ext.get(this.updateTextField).dom.value, this.format);
		}
		this.calendar.render(currentDate);
		
		Ext.getBody().un('click', this.hideCalendarEventFn);
				
		var popup = Ext.get('calendarPopUp' + this.calendarId);
		popup.setVisibilityMode(Ext.Element.DISPLAY);
		popup.show(true);
		popup.moveTo(event.getPageX(), event.getPageY());
		
		Ext.getBody().on('click', this.hideCalendarEventFn, this, { delay: 0 });
		
		currentDate = null;
		popup = null;
	},
	
	onSelect: function (date) {
		Ext.get(this.updateTextField).dom.value = date.format(this.format);
		var popup = Ext.get('calendarPopUp' + this.calendarId);
		popup.setVisibilityMode(Ext.Element.DISPLAY).hide();
	}

});

var DoubleMonthCalendar = Class.create ({
	
	//Html templates
	multipleCalendarTemplate: "<div id=\"calendar{calendarId}Wrapper\" class=\"doubleCalendar\"><div id=\"calendar{calendarId}-1Wrapper\" class=\"doubleCalendar1\"></div><div id=\"calendar{calendarId}-2Wrapper\" class=\"doubleCalendar2\"></div></div>",

	//Instance variables
	baseDate: today,
	calendarId: null,
	callbackFn: null,
	callbackFnScope: this,
	parentTag: null,
	firstMonthCalendar: null,
	secondMonthCalendar: null,	
	availableDatesStatus: null,
	restrictedRanges: [],
	daysToSelect: 1,

	//Initialization functions
	initialize: function (parentTag, calendarId, numberDaysToSelect) {
		
		this.calendarId = calendarId;
				
		this.multipleCalendarTemplate = new Ext.Template(this.multipleCalendarTemplate);
				
		this.parentTag = parentTag;
		
		if(numberDaysToSelect !== null) {
			this.daysToSelect = numberDaysToSelect;
		}

	},

	setOnSelectCallback: function (callback, scope) {
		this.callbackFn = callback;
		this.callbackFnScope = scope;
	},
	
	setDateRestrictions: function (availableDatesStatus, restrictedRanges) {
		if(availableDatesStatus !== null) {
			this.availableDatesStatus = availableDatesStatus;
		}
		
		if(restrictedRanges !== null) {
			this.restrictedRanges = restrictedRanges;
		}
		
		this.initializeRestrictedDates();
	},
	

	
	//Method to render the calendar
	//Param date = base date to use to render the calendars
	render: function (date) {
		if(date !== null) {
			this.baseDate = date;
		}
		var html = this.multipleCalendarTemplate.apply({ calendarId: this.calendarId });
			
		if(this.parentTag === null || this.parentTag == document) {
			Ext.getBody().insertHtml('beforeEnd', html);
		} else {
			Ext.get(this.parentTag).update(html);
		}
		 
		//Initializing the calendars
		this.firstMonthCalendar = new SingleMonthCalendar("calendar" + this.calendarId + "-1Wrapper", this.calendarId + "-1");
		this.secondMonthCalendar = new SingleMonthCalendar("calendar" + this.calendarId + "-2Wrapper", this.calendarId + "-2");
		
		//Hooking up the events handlers
		this.firstMonthCalendar.setOnSelectCallback(function(date) { this.onSelectDate.call(this, date, date.add(Date.DAY, (this.daysToSelect - 1))); }, this);
		this.secondMonthCalendar.setOnSelectCallback(function(date) { this.onSelectDate.call(this, date, date.add(Date.DAY, (this.daysToSelect - 1))); }, this);
		
		this.firstMonthCalendar.setOnMouseOverCallback(this.onMouseOver, this);
		this.secondMonthCalendar.setOnMouseOverCallback(this.onMouseOver, this);
		Ext.get('calendar' + this.calendarId + 'Wrapper').on('mouseout', this.onMouseOutCalendar, this);
		
		this.firstMonthCalendar.setOnSelectPreviousMonthCallback(this.previousMonthSelectorFn, this);
		this.firstMonthCalendar.setOnSelectNextMonthCallback(null);
		this.secondMonthCalendar.setOnSelectPreviousMonthCallback(null);
		this.secondMonthCalendar.setOnSelectNextMonthCallback(this.nextMonthSelectorFn, this);

		this.firstMonthCalendar.render(this.baseDate);
		this.secondMonthCalendar.render(this.baseDate.add(Date.MONTH, 1));
		this.renderRestrictedDates();
		
		html = null;
	},
	
	//private methods
	initializeRestrictedDates: function () {
		var newDateRangesRestriction = [];
		this.restrictedRanges.each(function (range) {
			newDateRangesRestriction.push(range);
		}, this);
		
		this.restrictedRanges = newDateRangesRestriction;
		
	},
	
	renderRestrictedDates: function () {
		var firstCalendarFirstDate = this.baseDate.getFirstDateOfMonth();
		var firstCalendarLastDate = this.baseDate.getLastDateOfMonth();
		var secondCalendarFirstDate = this.baseDate.add(Date.MONTH, 1).getFirstDateOfMonth();
		var secondCalendarLastDate = this.baseDate.add(Date.MONTH, 1).getLastDateOfMonth();

		//Clearing all the dates css classes
		Ext.get('calendar' + this.calendarId + "-1" + 'Body').select('td').each(function(elem) {
			elem.removeClass('unavailable');
			elem.removeClass('restricted');
			elem.removeClass('selected');
			elem.removeClass('highlight');
			elem.removeClass('blank');
		});
		Ext.get('calendar' + this.calendarId + "-2" + 'Body').select('td').each(function(elem) {
			elem.removeClass('available');
			elem.removeClass('unavailable');
			elem.removeClass('restricted');
			elem.removeClass('selected');
			elem.removeClass('highlight');
			elem.removeClass('blank');
		});

		var iteratingDate = firstCalendarFirstDate;
		while(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, secondCalendarLastDate)) {
			var hasDateStatus = this.hasDateStatus(iteratingDate);
			var isAnAvaibaleDate = this.isAnAvailableDate(iteratingDate);
			var isARestrictedDate = this.isWithinARestrictedRange(iteratingDate);
			var hasStartDateStatus = this.hasStartDateStatus(iteratingDate);
			var hasStartReservationDate = this.hasStartReservationDate(iteratingDate);
			
			if(!isAnAvaibaleDate) {
				if (hasDateStatus) {
					if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
						Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('unavailable');
					} else if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) {
						Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('unavailable');
					}
				} else {
					if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
						Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('blank');
					} else if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) {
						Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('blank');
					}
				}
			} else if(isARestrictedDate) {
				if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
					Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('restricted');
				} else if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) {
					Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('restricted');
				}
			} else {
				if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
				
					if(hasStartDateStatus){
						Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('no-start');
					} else if(hasStartReservationDate) {
						Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('available');
					} else {
						Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('available');
					}
				} else if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) {
					if(hasStartDateStatus){
						Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('no-start');
					}else if(hasStartReservationDate) {
						Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('available');
					} else {
						Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('available');
					}
				}
			}
			iteratingDate = iteratingDate.add(Date.DAY, 1);
			
			hasDateStatus = null;
			hasStartDateStatus = null;
			isARestrictedDate = null;
			isAnAvaibaleDate = null;
		}

		firstCalendarFirstDate = null;
		firstCalendarLastDate = null;
		iteratingDate = null;
		secondCalendarFirstDate = null;
		secondCalendarLastDate = null;
	},

	//private Event callback functions
	
	onSelectDate: function (fromDate, toDate) {
		if(jQuery('#unitSelectionPopUp').css('display') == 'block' && jQuery('#unitSelectionPopUp').css('visibility') == 'visible') {
			return false;
		}
		
		if(Ext.get('calendarAreaMessage') !== null){
			Ext.get('calendarAreaMessage').hide(true);
			Ext.get('calendarAreaMessage').setDisplayed(false);
		}
		
		var firstCalendarFirstDate = this.baseDate.getFirstDateOfMonth();
		var firstCalendarLastDate = this.baseDate.getLastDateOfMonth();
		var secondCalendarFirstDate = this.baseDate.add(Date.MONTH, 1).getFirstDateOfMonth();
		var secondCalendarLastDate = this.baseDate.add(Date.MONTH, 1).getLastDateOfMonth();
		var dateMonth1 = null;
		var dateMonth2 = null;
		var iteratingDate = fromDate;
		
		if(Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column') !== null) {
			dateMonth1 = Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column');
		}
		if(Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column') !== null) {
			dateMonth2 = Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column');
		}

		if(DateUtils.compareDates(toDate, secondCalendarLastDate) > 0 || this.isANotSelectableRange(fromDate, toDate)) {
			return;
		}		

		if(dateMonth1 !== null && dateMonth1.hasClass('no-start') === false) {
			Ext.get('calendar' + this.calendarId + "-1" + 'Body').select('td.selected').each(function(elem) {
				elem.removeClass('selected');
			});
		}
		if(dateMonth2 !== null && dateMonth2.hasClass('no-start') === false) {
			Ext.get('calendar' + this.calendarId + "-2" + 'Body').select('td.selected').each(function(elem) {
				elem.removeClass('selected');
			});
		}

		while(DateUtils.isDateInRange(iteratingDate, fromDate, toDate)) {
			if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
				if(dateMonth1 !== null && dateMonth1.hasClass('no-start') === false) {
					Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('selected');
					if(Ext.get('nextButtonArea') !== null) {
						Ext.get('nextButtonArea').show(true);
					}
				} else {
					return false;
				}
			} if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) { 
				if(dateMonth2 !== null && dateMonth2.hasClass('no-start') === false) {
					Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('selected');
					if(Ext.get('nextButtonArea') !== null) {
						Ext.get('nextButtonArea').show(true);
					}
				} else {
					return false;
				}
			}
			iteratingDate = iteratingDate.add(Date.DAY, 1);
		}

		if(this.callbackFn !== null) {
			this.callbackFn.call(this.callbackFnScope, fromDate, toDate);
		}
		
		dateMonth1 = null;
		dateMonth2 = null;
		firstCalendarFirstDate = null;
		firstCalendarLastDate = null;
		iteratingDate = null;
		secondCalendarFirstDate = null;
		secondCalendarLastDate = null;
	},
	
	previousMonthSelectorFn: function () {
		this.baseDate = this.baseDate.add(Date.MONTH, -1);
		this.firstMonthCalendar.render(this.baseDate);
		this.secondMonthCalendar.render(this.baseDate.add(Date.MONTH, 1));
		this.renderRestrictedDates();
	},

	nextMonthSelectorFn: function () {
		this.baseDate = this.baseDate.add(Date.MONTH, 1);
		this.firstMonthCalendar.render(this.baseDate);
		this.secondMonthCalendar.render(this.baseDate.add(Date.MONTH, 1));
		this.renderRestrictedDates();
	},

	onMouseOver: function(data) {
		var fromDate = data.date;
		var endDate = fromDate.add(Date.DAY, (this.daysToSelect - 1));
		var firstCalendarFirstDate = this.baseDate.getFirstDateOfMonth();
		var firstCalendarLastDate = this.baseDate.getLastDateOfMonth();
		var secondCalendarFirstDate = this.baseDate.add(Date.MONTH, 1).getFirstDateOfMonth();
		var secondCalendarLastDate = this.baseDate.add(Date.MONTH, 1).getLastDateOfMonth();

		var iteratingDate = fromDate;

		Ext.get('calendar' + this.calendarId + "-1" + 'Body').select('td.highlight').each(function(elem) {
			elem.removeClass('highlight');
		});
		Ext.get('calendar' + this.calendarId + "-2" + 'Body').select('td.highlight').each(function(elem) {
			elem.removeClass('highlight');
		});

		 
		if(DateUtils.compareDates(endDate, secondCalendarLastDate) <= 0 && !this.isANotSelectableRange(fromDate, endDate)) {
			while(DateUtils.isDateInRange(iteratingDate, fromDate, endDate)) {
				if(DateUtils.isDateInRange(iteratingDate, firstCalendarFirstDate, firstCalendarLastDate)) {
					Ext.get('calendar' + this.calendarId + "-1" + 'Day' + iteratingDate.getDate() + 'Column').addClass('highlight');
				}
				if(DateUtils.isDateInRange(iteratingDate, secondCalendarFirstDate, secondCalendarLastDate)) { 
					Ext.get('calendar' + this.calendarId + "-2" + 'Day' + iteratingDate.getDate() + 'Column').addClass('highlight');
				}
				iteratingDate = iteratingDate.add(Date.DAY, 1);
			}
		}
		
		endDate = null;
		firstCalendarFirstDate = null;
		firstCalendarLastDate = null;
		fromDate = null;
		iteratingDate = null;
		secondCalendarFirstDate = null;
		secondCalendarLastDate = null;
	},
	

	onMouseOutCalendar: function(event) {
		Ext.get('calendar' + this.calendarId + "-1" + 'Body').select('td.highlight').each(function(elem) {
			elem.removeClass('highlight');
		});
		Ext.get('calendar' + this.calendarId + "-2" + 'Body').select('td.highlight').each(function(elem) {
			elem.removeClass('highlight');
		});
	},
	
	//UtilityMethods
	isWithinARestrictedRange: function (date) {
		if(this.restrictedRanges.length < 1) {
			return false;
		}
		for(var i = 0; i < this.restrictedRanges.length; i++) {
			if(DateUtils.isDateInRange(date, this.restrictedRanges[i].fromDate, this.restrictedRanges[i].toDate)) {
				return true;
			}
		}
		return false;
	},

	hasDateStatus: function (date) {
		if(this.availableDatesStatus === null) {
			return false;
		}
		for(var i = 0; i < this.availableDatesStatus.length; i++) {
			if(DateUtils.compareDates(date, this.availableDatesStatus[i].dateCalendar) === 0) {
				return true;
			}
		}
		return false;
	},
	
	hasStartDateStatus: function (date) {
		if(this.availableDatesStatus === null) {
			return true;
		}
		for(var i = 0; i < this.availableDatesStatus.length; i++) {
			if(DateUtils.compareDates(date, this.availableDatesStatus[i].dateCalendar) === 0) {
				if(this.availableDatesStatus[i].startDateStatus == '0') {
					return true;
				} else {
					return false;
				}
			}
		}
		return false;
	},
	
	hasStartReservationDate: function (date) {
		if(this.availableDatesStatus === null) {
			return true;
		}
		for(var i = 0; i < this.availableDatesStatus.length; i++) {
			if(DateUtils.compareDates(date, this.availableDatesStatus[i].dateCalendar) === 0) {
				if(this.availableDatesStatus[i].startReservationDate != 0) {
					return true;
				} else {
					return false;
				}
			}
		}
		return false;
	},
	
	
	isAnAvailableDate: function (date) {
		if(this.availableDatesStatus === null) {
			return true;
		}
		for(var i = 0; i < this.availableDatesStatus.length; i++) {
			if(DateUtils.compareDates(date, this.availableDatesStatus[i].dateCalendar) === 0) {
				if(this.availableDatesStatus[i].availabilityStatus == '01') {
					return true;
				} else {
					return false;
				}
			}
		}
		return false;
	},
	
	isANotSelectableRange: function (date1, date2) {
		var date2Padded = DateUtils.compareDates(date1, date2)===0?date2:date2.add(Date.DAY, -1);
		if(this.availableDatesStatus !== null) {
			var iteratingDate = date1;
			while(DateUtils.isDateInRange(iteratingDate, date1, date2Padded)) {
				if(!this.isAnAvailableDate(iteratingDate)) {
					return true;
				}
				iteratingDate = iteratingDate.add(Date.DAY, 1);
			}
			iteratingDate = null;
		}
		for(var i = 0; i < this.restrictedRanges.length; i++) {
			var range = this.restrictedRanges[i];
			if(DateUtils.compareDates(date1, range.toDate) <= 0 && DateUtils.compareDates(date2, range.fromDate) > 0 && !(DateUtils.compareDates(date1, range.fromDate) <= 0 && DateUtils.compareDates(date2, range.toDate) >= 0)) {
				return true;
			}
			range = null;
		}
		date2Padded = null;
		
		return false;
	}
});
