var calendar = {
	idCalendar: "calendar",
	strConstants: {
		months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
		days: ["S", "M", "T", "W", "T", "F", "S"]

	}
	,

	iDate: {day: 0, month: 0, year: 0}
	,
	
	cDate: {day: 23, month: 12, year: 2007}
	,

	availableDateInterval: {from:{day: 0, month: 0, year: 0}, to:{day: 0, month: 0, year: 0}}
	,
	
	validDateInterval: {from:{day: 0, month: 0, year: 0}, to:{day: 0, month: 0, year: 0}}
	,

	inputFunc: function(){},
	outFunc: function(){},
	sources: null,
	
	isInit: false,

	init: function() {
		var cbStack = [];
		cbStack[cbStack.length] = {handler:calendar.doInit,scope:calendar,params:[null,cbStack]}	
		popupFramework.create({id:this.idCalendar,requestURL:'CalendarPopupForward.do',opacity:true,templateName:this.idCalendar,position:'centered'},cbStack)
	}
	,
	doInit: function(params,cbStack) {
		this.strConstants = popupFramework.popups[this.idCalendar].strConstants; 
		this.isInit = true;			
	}
	,
	
	show: function(params) {
		if(!this.isInit){
			return false;
		}
		
		if(params){
			if(params.sources){
				this.sources = params.sources;	
			}

			this.inputFunc = (params.inputFunc)? params.inputFunc : this.defaultInputFunc; 
			this.outFunc = (params.outFunc)? params.outFunc : this.defaultOutFunc;
			
		} 
		
		this.inputFunc(this.sources);
		this.drawCurrentMonth(this.idCalendar+'MonthBlock1', this.cDate);
		var secDate = this.shiftMonth(this.cDate, 1);
			secDate.day = 0;
		this.drawCurrentMonth(this.idCalendar+'MonthBlock2', secDate);				
		popupFramework.show({id:this.idCalendar,opacity:true,templateName:this.idCalendar,position:'centered'});		
		
		return true;
	}	
	,
	
	refresh: function() {
		this.drawCurrentMonth(this.idCalendar+'MonthBlock1', this.cDate);
		var secDate = this.shiftMonth(this.cDate, 1);
			secDate.day = 0;
		this.drawCurrentMonth(this.idCalendar+'MonthBlock2', secDate);
	}	
	,
	
	hide: function(config) {
		popupFramework.hide(config);
	}	
	,	
	
	drawCurrentMonth: function(calendarContainer, date){
		var t = new Date();
		var tDate = {day: t.getDate(), month: t.getMonth(), year: t.getFullYear()};
		
		var tValidFirstDate = (this.validDateInterval.from.year)? new Date(this.validDateInterval.from.year,
																			this.validDateInterval.from.month,
																			this.validDateInterval.from.day) : null;
		var tValidLastDate = (this.validDateInterval.to.year)? new Date(this.validDateInterval.to.year,
																			this.validDateInterval.to.month,
																			this.validDateInterval.to.day) : null;
			
		var str='';
		str+='<h3>' + this.strConstants.months[date.month] + ', ' + date.year + '</h3>';
		
		
		str+='<table cellpadding="0" cellspacing="0" border="0" class="calMonth">'+
				'<tr class="calMonthDays">';
		for(var i=0; i<this.strConstants.days.length; i++){
			str+='<th '+((i==0)?'class="calMonthLeft"':(i==this.strConstants.days.length-1)?'class="calMonthRight"':"")+'>' + this.strConstants.days[i] + '</th>';
		} 
		str+='</tr>';
		
		var firstDay = this.getWeekDay(1, date.month, date.year);
			firstDay = (firstDay)?firstDay:7;
		var maxDay = this.getMaxDay(date.month, date.year)
		
		var col;
		var row = 0;
		
		str+='<tr>';
		var prevMonthDate = this.shiftDay(new Date(date.year,date.month,1), -firstDay);
		for(col=0; col<firstDay; col++){
			if((tValidFirstDate && tValidFirstDate.getTime() > prevMonthDate.getTime()) || (tValidLastDate && tValidLastDate.getTime() < prevMonthDate.getTime())){
				str+='<td class="calDayPast' + ((col==6)?' noBorder':'') + '">' + prevMonthDate.getDate() + '</td>';	
			}
			else{		 
				str+='<td class="' + ((col==6)?' noBorder':'') + '">' + prevMonthDate.getDate() + '</td>';	
			}	
			prevMonthDate = this.shiftDay(prevMonthDate, 1);
			if (col == 6){
				col = 0;
				row++;
				str+='</tr>';
				break;
			}						
		}
		
		for(var i=0; i<maxDay; i++){
			var dayCss = "";	
			var tFormattedDate = new Date(date.year,date.month,(i+1));
			
			if((tValidFirstDate && tValidFirstDate.getTime() > tFormattedDate.getTime()) || (tValidLastDate && tValidLastDate.getTime() < tFormattedDate.getTime())){
				str+='<td class="calDayPast">' + (i+1) + '</td>';	
			}
			else{	
				if(this.iDate.day == (i+1) && this.iDate.month == date.month && this.iDate.year == date.year){
					dayCss+=' calDaySelect';			
				} 
				else if(tDate.day == (i+1) && tDate.month == date.month && tDate.year == date.year){
					dayCss+=' calDayToday';				
				} 			
				
				str+='<td class="' + dayCss + ((col==6)?' noBorder':'') + '"><a href="#" onclick="calendar.setDay({year:'+date.year+',month:'+date.month+',day:'+(i+1)+'});return false">' + (i+1) + '</a></td>';					
			}	
			
			if (++col == 7){
				col = 0;
				row++;
				str+='</tr>';
			}
		}		
		
		var nextMonthDate = this.shiftDay(new Date(date.year,date.month,maxDay), 1)
		for(; row<6;){
			if((tValidFirstDate && tValidFirstDate.getTime() > nextMonthDate.getTime()) || (tValidLastDate && tValidLastDate.getTime() < nextMonthDate.getTime())){
				str+='<td class="calDayPast' + ((col==6)?' noBorder':'') + '">' + nextMonthDate.getDate() + '</td>';	
			}
			else{		 
				str+='<td class="' + ((col==6)?' noBorder':'') + '">' + nextMonthDate.getDate() + '</td>';	
			}	
			nextMonthDate = this.shiftDay(nextMonthDate, 1)
			
			if (++col == 7){
				col = 0;
				row++;
				str+='</tr>';
			}							
		}		
		
		str+=''+		
			'</table>';		
			
		Ext.get(calendarContainer).dom.innerHTML = str;
				
	}
	,
	
	setDay: function(date){
		this.cDate = date;
		this.outFunc(this.sources,this.cDate);
		this.hide({id:this.idCalendar});
	}
	,
	
	shiftDay: function(date, nDay){
		var dt = (date instanceof Date) ? date : new Date(date.year,date.month,date.day);
		var newDt = new Date(dt.getTime() + nDay*24*60*60*1000);
		return (date instanceof Date) ? newDt : {day:newDt.getDate(),month:newDt.getMonth(),year:newDt.getFullYear()};
	}
	,
	
	shiftMonth: function(date, nMonth){
		var dt = (date instanceof Date) ? date : new Date(date.year,date.month,date.day);
		
		var dd = dt.getDate();
		var mm = dt.getMonth() + nMonth;
		var yy = dt.getFullYear() + Math.floor(mm / 12);
		mm %= 12;
		if (mm < 0) mm += 12;
		var maxDay = this.getMaxDay(mm,yy);
		if (maxDay < dd) dd = maxDay;
		
		if (date instanceof Date) {
			dt.setDate(dd);
			dt.setMonth(mm);
			dt.setFullYear(yy);
			return dt;
		}		
		return {day:dd,month:mm,year:yy};
	}
	,
	
	prevMonth: function(){
		this.cDate = this.shiftMonth(this.cDate,-1);
		this.refresh();	
	}	
	,
	
	nextMonth: function(){
		this.cDate = this.shiftMonth(this.cDate,1);	
		this.refresh();		
	}	
	,
	
	getMaxDay: function(month,year){
		var d = new Date (year,month+1,0);
		return d.getDate();
	}
	,
	
	getWeekDay: function(day,month,year){
		var d = new Date (year,month,day);
		return d.getDay();
	}
	,
		
	defaultInputFunc: function(sources) {
		this.availableDateInterval = {from:{day: 0, month: 0, year: 0}, to:{day: 0, month: 0, year: 0}};
		this.validDateInterval = {from:{day: 0, month: 0, year: 0}, to:{day: 0, month: 0, year: 0}}	
	
		var day = Ext.get(sources.idDaysField).getValue();	
		var month = 0;
		var year = 0;
		var dt = Date.parseDate("1-" + Ext.get(sources.idMonthYearField).getValue(), Date.patterns.DayMonthYear);
		if(dt) {
			month = dt.getMonth();
			year = dt.getFullYear();			
			day = (dt.getDaysInMonth()<day) ? dt.getDaysInMonth() : day;
		}		
		
		with(this){		
			iDate.day = cDate.day = day;
			iDate.month = cDate.month = month;
			iDate.year = cDate.year = year;
		}		
	}
	,
	
	defaultOutFunc: function(sources,date) {
		var dt = new Date(date.year,date.month,date.day);
		
		var oDaysField = Ext.get(sources.idDaysField);
		var oMonthYearField = Ext.get(sources.idMonthYearField);	
		
		this.setSelectValue(oMonthYearField, dt.format(Date.patterns.MonthYear));
		
		if(oMonthYearField.dom.onchange){
			oMonthYearField.dom.onchange();
		}
  
		this.setSelectValue(oDaysField,date.day);
		if(oDaysField.dom.onchange){
			oDaysField.dom.onchange();
  		}
	}
	,
	
	setSelectValue: function(s,v) { /* must be mooved in core functionality */
		oS = Ext.get(s).dom;
		for (var i=0; i<oS.length; i++) {
			if(oS.options[i].value == v){
				oS.options[i].selected = true;
				return true;
			}
		}
		return false;	
	}	
	
}	


/* extended functions for calendar */

function calendarDepartureInputFunc (sources) {
	var today = new Date();
	var bookingBuffer = (sources.bookingBuffer) ? sources.bookingBuffer : 0;
	tFirstAvailDate = this.shiftDay(today, bookingBuffer);
	tLastAvailDate = this.shiftDay(today, 330);
	
	this.availableDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};
	this.validDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};

	var day = Ext.get(sources.idDaysField).getValue();	
	var month = 0;
	var year = 0;
	var dt = Date.parseDate("1-" + Ext.get(sources.idMonthYearField).getValue(), Date.patterns.DayMonthYear);
	if(dt) {
		month = dt.getMonth();
		year = dt.getFullYear();
		day = (dt.getDaysInMonth()<day) ? dt.getDaysInMonth() : day;					
	}		
	
	with(this){		
		iDate.day = cDate.day = day;
		iDate.month = cDate.month = month;
		iDate.year = cDate.year = year;
	}	
}

function calendarOutboundInputFunc (sources) {
	var today = new Date();
	var bookingBuffer = (sources.bookingBuffer) ? sources.bookingBuffer : 0;
	var tFirstAvailDate = this.shiftDay(today, bookingBuffer);
	var tLastAvailDate = this.shiftDay(today, 330);
	
	this.availableDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};
	this.validDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};

	var day = Ext.get(sources.idDaysField).getValue();	
	var month = 0;
	var year = 0;
	var dt = Date.parseDate("1-" + Ext.get(sources.idMonthYearField).getValue(), Date.patterns.DayMonthYear);
	if(dt) {
		month = dt.getMonth();
		year = dt.getFullYear();	
		day = (dt.getDaysInMonth()<day) ? dt.getDaysInMonth() : day;				
	}		
	
	with(this){		
		iDate.day = cDate.day = day;
		iDate.month = cDate.month = month;
		iDate.year = cDate.year = year;
	}	
}


function calendarInboundInputFunc (sources) {
	var today = new Date();
	var bookingBuffer = (sources.bookingBuffer) ? sources.bookingBuffer : 0;
	var tFirstAvailDate = this.shiftDay(today, bookingBuffer);
	var tLastAvailDate = this.shiftDay(today, 330);
	
	var extraDate = Date.parseDate("1-" + Ext.get(sources.idExtraMonthYearField).getValue(), Date.patterns.DayMonthYear);
		extraDate.setDate(Ext.get(sources.idExtraDaysField).getValue());

	tFirstAvailDate = (tFirstAvailDate.getElapsed(extraDate)<0) ? tFirstAvailDate : extraDate;
	
	this.availableDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};
	this.validDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};

	var day = Ext.get(sources.idDaysField).getValue();	
	var month = 0;
	var year = 0;
	var dt = Date.parseDate("1-" + Ext.get(sources.idMonthYearField).getValue(), Date.patterns.DayMonthYear);
	if(dt) {
		month = dt.getMonth();
		year = dt.getFullYear();
		day = (dt.getDaysInMonth()<day) ? dt.getDaysInMonth() : day;					
	}		
	
	with(this){		
		iDate.day = cDate.day = day;
		iDate.month = cDate.month = month;
		iDate.year = cDate.year = year;
	}	
}

function calendarHotelCheckInInputFunc (sources) {
	var today = new Date();
	var bookingBuffer = (sources.bookingBuffer) ? sources.bookingBuffer : 0;
	var tFirstAvailDate = this.shiftDay(today, bookingBuffer);
	var tLastAvailDate = this.shiftMonth(today, 11);
	var availTimeFrame = (sources.availTimeFrame) ? sources.availTimeFrame : null;	
	if(availTimeFrame){
		tLastAvailDate = today;
		for(var i in availTimeFrame){			
			switch(i){
				case "days":
					tLastAvailDate = this.shiftDay(tLastAvailDate, availTimeFrame[i]);
					break;
				case "months":
					tLastAvailDate = this.shiftMonth(tLastAvailDate, availTimeFrame[i]);
					break;
			}
		}
	}
	
	this.availableDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};
	this.validDateInterval = {from:{day: tFirstAvailDate.getDate(), month: tFirstAvailDate.getMonth(), year: tFirstAvailDate.getFullYear()}, to:{day: tLastAvailDate.getDate(), month: tLastAvailDate.getMonth(), year: tLastAvailDate.getFullYear()}};

	var day = Ext.get(sources.idDaysField).getValue();	
	var month = 0;
	var year = 0;
	var dt = Date.parseDate("1-" + Ext.get(sources.idMonthYearField).getValue(), Date.patterns.DayMonthYear);
	if(dt) {
		month = dt.getMonth();
		year = dt.getFullYear();	
		day = (dt.getDaysInMonth()<day) ? dt.getDaysInMonth() : day;				
	}		
	
	with(this){		
		iDate.day = cDate.day = day;
		iDate.month = cDate.month = month;
		iDate.year = cDate.year = year;
	}	
}

onloadGlobalHandler.addAction("initCalendar", function(){calendar.init()});
