// Calendar
//
// Usage: including the following in your html where you want the controls to be.
//
//	<script language="JavaScript">
//		InsertCalendar('depart','DateOut',outDate, maxDate, minDate);
//	</ script>
//
// Where: 
//	'depart' is the text id of the calendar
//	'DateOut' is the text name of the parameter that appears upon form submittion in the requested url
//	outdate is a Date() object representing the initially selected date
//	maxDate is a Date() object representing the maximum date in allowed the date range 
//	minDate is a Date() object representing the minimum date in allowed the date range 
//
// Don't forget to include this script in the top of your HTML page, like this
// 		<script type="text/javascript" language="javascript" src="Calendar.js" />
//

_addCalendars = new Array();

function Calendar(id, name, date, maxDate, minDate){
	if(id){
		this.init(id, name, date, maxDate, minDate)
	}
}

function InsertCalendar(id, name, date, maxDate, minDate)
{
	cal = _createCalendar(id, name, date, maxDate, minDate);
	if(cal!=null) cal.insertInDocument();
} 

function _createCalendar(id, name,date, maxDate, minDate)
{
	if(getCalendar(id)!= null)
		alert('Error - Two calendars have the same id');
	else {
		calendar = new Calendar(id, name, date, maxDate, minDate);
		_addCalendars.push(calendar);
		return calendar;
	}
	return null;
}

function getCalendar(id)
{
    for (i = 0; i < _addCalendars.length; i++)
	{
		if (_addCalendars[i].getID() == id) return _addCalendars[i];
	}
	return null;
}

function drawMonthsList(id, minMonth, minYear) {

	

    var m = minMonth; 
    var y = minYear;
    var writeString = "<tr class='Webjet_Calendar_MonthsList'><td colspan='7'><table class='CalendarMonthsList' style='width: 100%'><tr>";
    
    
   
    
    for (var mi = 0; mi < 12; mi++) {
                
        var sMonthShort = monthNames[m - 1].substring(0, 3); 
        
        
        var sTd = "<td align=center><a id=" + sMonthShort + "_" + id + " style='text-decoration:none; font-size: 12px !important;' href=\"javascript:getCalendar('" + id + "').setMonth('" + y + "','" + m + "');\">" + sMonthShort + "</a></td>";
        
        
        
        writeString += sTd;
        if (mi == 5)//after first 6 months
        {
            writeString += "</tr><tr>";
        }
        m++;
        if (m == 13) {
            m = 1;
            y++;
        }
    }
    writeString += "</tr></table></td></tr>";
    return writeString;
}



function hideAllCalendars()
{
    for (i = 0; i < _addCalendars.length; i++)
       _addCalendars[i].hide();
}

Calendar.prototype = {
  // public methods
  	init : function(id, name, date, maxDate, minDate) {
		this.id = id;
		this.name = name;
		this.date = date;
		this.maxDate = maxDate;
		this.minDate = minDate;
		
		// this is an optimisation to stop a control updating if it was the trigger of the update.
		this.updateSource = null; 
	},
	insertInDocument : function ()
	{
		this._insertOutputControl();
		this._insertDayControl();
		this._insertMonthYearControl();
		this._insertCalendarIcon();
		this._insertCalendarControl();
		this._initializeControls();
		this._update();
	},
	_insertOutputControl : function()
	{
		outputControlId = this.id+"_out";
		document.write("<input name='"+this.name+"' id='"+ outputControlId +"' type='hidden'>");
		this.outputControl = document.getElementById(outputControlId);
	},
	_insertDayControl : function()
	{
		daySelectControlId = this.id + "_day";
		document.write(" <select id='"+daySelectControlId+"' language='javascript' onchange='getCalendar(\""+this.id+"\").dayControlChanged();'></select>");
		this.daySelectControl = document.getElementById(daySelectControlId);
	},
	_insertMonthYearControl : function()
	{
		monthSelectControlId = this.id + "_month";
		document.write(" <select id='"+monthSelectControlId+"' language='javascript' onchange='getCalendar(\""+this.id+"\").monthControlChanged();'></select>");
		this.monthSelectControl = document.getElementById(monthSelectControlId);
	},
		_insertCalendarIcon : function()
	{
		document.write(" <a href='javascript:getCalendar(\""+this.id+"\").toggle()'>");
		document.write(" <img alt='Pick Date' src='http://www.webjet.com.au/images/calendar.gif' border='0' style='vertical-align: bottom;'></a>");
	},
	_insertCalendarControl : function()
	{
		document.write("<div>");

		calendarControlId = this.id + "_calendar";
		document.write("<table id='" + calendarControlId + "' border='0' cellpadding=1 cellspacing=0 style='display:none ;border-width:3px;border-style:solid;border-collapse:collapse; border-color: #CCC' class='WebjetCalendarGlobal'>");
		this.calendarControl = document.getElementById(calendarControlId);
    		
    		document.write(drawMonthsList(this.id,this.date.getMonth()+1,this.date.getFullYear()));
    		
    		//alert(drawMonthsList(this.id,this.date.getMonth(),this.date.getFullYear()));
    		
		this._insertCalendarControlHeaderRow();
		this._insertCalendarControlDayNamesRow();  
		this._insertCalendarControlDateCells();
			    
		document.write("</table>");
		document.write("</div>");
	},
	_insertCalendarControlDateCells : function()
	{
		this.dateCells = new Array(6);
		this.dateCellsText = new Array(6);
		for (w = 0; w < 6; w++) 
		{
			this.dateCells[w] = new Array(7);
			this.dateCellsText[w] = new Array(7);
			document.write("<tr valign=top>");
			for (d = 0; d < 7; d++) 
			{			
				var dateCellId = this.id + "_cell" + "_" + w + "_" + d;
				document.write("<td id=" + dateCellId + " align='center' valign='middle' width='20' height='20' >");
				this.dateCells[w][d] = document.getElementById(dateCellId);

				var dateCellTextId = this.id + "_cellText_" + "_" + w + "_" + d;
				document.write("<a id=" + dateCellTextId + " class='Webjet_Calendar_Day' day=" + this.date.getDate() + "> </a>");
				this.dateCellsText[w][d] = document.getElementById(dateCellTextId);

				document.write("</td>");
			}
			document.write("</tr>");
		}
	},
	_insertCalendarControlDayNamesRow : function()
	{
		document.write("<tr>");
		for (i = 0; i < 7; i++)
		{
			document.write("<td class='Webjet_Calendar_WeekDay'>" + dayNames[i] + "</td>");
		}
		document.write("</tr>");
	},
	_insertCalendarControlHeaderRow : function()
	{
		document.write("<tr class='Webjet_Calendar_Month'>");

		this._insertPreviousMonthControl();
		this._insertCurrentMonthControl();
		this._insertNextMonthControl();

		document.write("</tr>");
	},
	_insertNextMonthControl : function()
	{
		nextMonthControlId = this.id + "_nextMonth";
		document.write("<td align=right><a id=" + nextMonthControlId + " style='text-decoration:none' href=\"javascript:getCalendar('"+this.id+"').nextMonth();\">&gt;</a></td>");
		this.nextMonthControl = document.getElementById(nextMonthControlId);
	},
	_insertCurrentMonthControl : function()
	{
		currentMonthControlId = this.id + "_currentMonth";
		document.write("<td align='center' colspan=5 id=" + currentMonthControlId + " style='text-align: center'></td>");
		this.currentMonthControl = document.getElementById(currentMonthControlId);
	},
	_insertPreviousMonthControl : function()
	{
		previousMonthControlId = this.id + "_previousMonth";
		document.write("<td align=left><a id=" + previousMonthControlId + " style='text-decoration:none' href=\"javascript:getCalendar('"+this.id+"').previousMonth();\">&lt;</a></td>");
		this.previousMonthControl = document.getElementById(previousMonthControlId);	
	},
	_initializeControls : function()
	{
		this._initializeDayControl();
		this._initializeMonthControl();
	},
	_initializeDayControl : function()
	{
		this._adjustNumDaysInDayControl();
	},
	_adjustNumDaysInDayControl : function()
	{
		firstDay = 1;
		//lastDay = getDaysInMonth(this.date.getFullYear(),this.date.getMonth());
		lastDay = 31;
	
		if ( this.date.getFullYear() == this.minDate.getFullYear() && this.date.getMonth() == this.minDate.getMonth())
		{
			firstDay = this.minDate.getDate();
		}
		if ( this.date.getFullYear() == this.maxDate.getFullYear() && this.date.getMonth() == this.maxDate.getMonth())
		{
			lastDay = this.maxDate.getDate();
		}
		
		this._removeAllDaysFromDayControl();
		this._addDaysToDayControl (firstDay, lastDay);
	},
	_removeAllDaysFromDayControl : function()
	{
		jQuery(this.daySelectControl).html("");
		// try putting options.length = 0;
	},
	_addDaysToDayControl : function(firstDay, lastDay)
	{
		selectedMonth = this.date.getMonth();
		selectedYear  = this.date.getFullYear();
		var dayIndex = getIndexOfDayNameOfFirstDayOfMonth(selectedYear, selectedMonth, firstDay);
				
		var list = this.daySelectControl; 
		var selectedDay = this.date.getDate();
		var index=0;
		for ( num = firstDay; num <= lastDay; ++num)
		{
			if(dayIndex >= dayNames.length) dayIndex = 0
			//text = dayNames[dayIndex++] + " " + num;
			text = num;
			list.options[index++]= new Option(text,num);
			if(num == selectedDay) list.options[index-1].selected = true;
		}
	},
	_initializeMonthControl : function()
	{
		selectedMonth = this.date.getMonth();
		selectedYear  = this.date.getFullYear();

		months=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec");
		var index = 0;
		for ( y = this.minDate.getFullYear(); y <= this.maxDate.getFullYear(); ++y)
		{
			for ( m=0; m<months.length; ++m)
			{
				if(
					!( y == this.maxDate.getFullYear() && m > this.maxDate.getMonth())
						&&
					!( y == this.minDate.getFullYear() && m < this.minDate.getMonth())
				)
				{ 
					text = months[m]+" "+ y;
					oOption = new Option(text,y +"/"+(m+1));
					this.monthSelectControl.options[index++] = oOption;
					if (m == selectedMonth && y == selectedYear) oOption.selected = true;
				}
			}
		}	
	},
	dayControlChanged :function()
	{
		this.updateSource = this.daySelectControl;
		this._setDateFromControls();
//		this.hide();
	},
	monthControlChanged :function()
	{
		this.updateSource = this.monthSelectControl;
		this._setDateFromControls();
//		this.hide();
	},
	toggle : function() {
		if ( this._isHidden() )
		{
			this.display();
		}
		else this.hide(); 
	},
	display : function() {
		this.calendarControl.style.display = 'block';
		this._update();
	},
	previousMonth : function() {
		this._setDate(this.date.getFullYear(),this.date.getMonth()-1,this.date.getDate());
	},
	nextMonth : function() {
		this._setDate(this.date.getFullYear(),this.date.getMonth()+1,this.date.getDate());
	},
	setMonth : function(year, month) {
		this._setDate(year,month-1,this.date.getDate());
	},
	
	getID : function() {
		return this.id;
	},
	hide : function() {
		this.calendarControl.style.display = 'none';
	},
	_isHidden : function() {
		return this.calendarControl.style.display == 'none';
	},
	selectDay : function (day)
	{
		this._setDate(this.date.getFullYear(),this.date.getMonth(),day);
		this.hide();
	},
	// private methods
	_setDate : function(year,month,day) {
		newDate = new Date(year,month,day);
		// sometimes if the month has changed this can be an invalid date. 31st of Feb for example.  
		if ( newDate.getDate()!=day ) newDate = new Date(year,month+1,0); // last day of the month selected

		if ( newDate < this.minDate )
			newDate = new Date(this.minDate);

		if ( newDate > this.maxDate )
			newDate = new Date(this.maxDate);		

		this.date = newDate;
		this._update();
	},
	_update : function()
	{
		this._updateCalendarControl();
		this._updateMonthAndYearControl();
		this._updateDayControl();
		this._updateOutputControl();

		this.updateSource = null;				
	},
	_updateCalendarControl : function()
	{
		var dayList = buildDayList(this.date.getFullYear(),this.date.getMonth());

		for (w = 0; w < 6; w++) 
		{
			for (d = 0; d < 7; d++) 
			{
				var dayOfMonth = this._getDayOfMonth(dayList[w][d]);
				var dateBit = this.dateCellsText[w][d];
				var dateCell = this.dateCells[w][d];
				jQuery(dateBit).html(dayOfMonth);

				dateCell.className = "Webjet_Calendar_Clear";
				
				if (dayOfMonth == "" || this._isBeforeMinDate(dayOfMonth, this.date.getMonth(), this.date.getFullYear()) || this._isAfterMaxDate(dayOfMonth, this.date.getMonth(), this.date.getFullYear()))
				{
					dateBit.style.textDecoration = "line-through";
					dateBit.href = "javascript:;";
					dateBit.className = "Webjet_Calendar_DayUnavailable";
				}
				else
				{
					dateBit.style.textDecoration = "none";
					if (dayList[w][d] == this.date.getDate()) 
					{
						dateCell.className += "Selected";
						dateBit.className = "Webjet_Calendar_DaySelected";
					}
					else
					{
						dateBit.className = "Webjet_Calendar_Day";					
					}
					dateBit.href="javascript:getCalendar('"+this.id+"').selectDay(" + dayOfMonth + ");";
				}
			}
		}
		jQuery(this.currentMonthControl).html(monthNames[this.date.getMonth()] + " " + this.date.getFullYear());
		this._setLimits();  	
	},	
	_setLimits : function()
	{	
		month = this.date.getMonth();
		year = this.date.getFullYear();
		jQuery(this.nextMonthControl).html((year == this.maxDate.getFullYear() && month == this.maxDate.getMonth()) ? "" : "&gt;");
		jQuery(this.previousMonthControl).html((year == this.minDate.getFullYear() && month == this.minDate.getMonth()) ? "" : "&lt;");
	},
	_updateMonthAndYearControl : function()
	{
		if ( this.updateSource != this.monthSelectControl )
		{ 
			month = this.date.getMonth()+1;
			year = this.date.getFullYear();
			monthYear = year + "/" + month;
			// find entry in monthyear controls list by value
			for (i = 0; i < this.monthSelectControl.options.length; i++)
			{
				if (this.monthSelectControl.options[i].value == monthYear) 
				{
					this.monthSelectControl.selectedIndex = i;
				break;
				}
			}
		}
	},
	_updateDayControl : function()
	{
		if ( this.updateSource != this.daySelectControl )
		{
			this._initializeDayControl();
		}
	},
	_updateOutputControl : function ()
	{
		this.outputControl.value = this.date.getFullYear() + "/" + (this.date.getMonth()+1) + "/" + this.date.getDate();
	},
	_setDateFromControls : function ()
	{
		day = this._getDayFromControl();
		month = this._getMonthFromControl();
		year = this._getYearFromControl();
		this._setDate(year,month,day);
	},
	_getYearFromControl : function ()
	{
		return this.monthSelectControl.value.split("/")[0];
	},
	_getMonthFromControl : function ()
	{
		return this.monthSelectControl.value.split("/")[1]-1;
	},
	_getDayFromControl : function ()
	{
		return this.daySelectControl.value;
	},
	_getDayOfMonth : function(d)
	{
		return isNaN(d) ? "" : d;
	},
	_isBeforeMinDate: function (day, month, year)
	{
		return new Date(year, month, day) < this.minDate;
	},
	_isAfterMaxDate: function (day, month, year)
	{
		return new Date(year, month, day) > this.maxDate;
	}
}

/// helpers

function getDaysInMonth(year, month) 
{
    var dayBeforeNextMonth = new Date(year, month+1, 0);
    return dayBeforeNextMonth.getDate();
}

function getIndexOfDayNameOfFirstDayOfMonth(year, month, day)
{
	var firstDayOfMonth = new Date(year,month,day);
	return firstDayOfMonth.getDay();
}

function buildDayList(year, month) 
{
    var dayList = new Array();
    dayList[0] = new Array(7);
    dayList[1] = new Array(7);
    dayList[2] = new Array(7);
    dayList[3] = new Array(7);
    dayList[4] = new Array(7);
    dayList[5] = new Array(7);
    var monthCal = new Date(year, month, 1);
    var firstDay = monthCal.getDay();
    var daysInMonth = getDaysInMonth(year,month);
    var actualDate = 1;
    var i, d, w;
    for (d = firstDay; d < 7; d++) 
    {
        dayList[0][d] = actualDate;
        actualDate++;
    }
    for (w = 1; w < 6; w++) 
    {
        for (d = 0; d < 7; d++) 
        {
            if (actualDate <= daysInMonth) 
            {
                dayList[w][d] = actualDate;
                actualDate++;
            }
        }
    }
    return dayList;
}

var monthNames;
function buildMonthNames()
{
    monthNames = new Array(12);
    monthNames[0] = "January";
    monthNames[1] = "February";
    monthNames[2] = "March";
    monthNames[3] = "April";
    monthNames[4] = "May";
    monthNames[5] = "June";
    monthNames[6] = "July";
    monthNames[7] = "August";
    monthNames[8] = "September";
    monthNames[9] = "October";
    monthNames[10] ="November";
    monthNames[11] ="December";
    return monthNames;
}
buildMonthNames();

var dayNames;
function buildDayNames()
{
    dayNames = new Array(7);
    dayNames[0] = "Sun";
    dayNames[1] = "Mon";
    dayNames[2] = "Tue";
    dayNames[3] = "Wed";
    dayNames[4] = "Thu";
    dayNames[5] = "Fri";
    dayNames[6] = "Sat";
}
buildDayNames();

function twoDigit(d)
{
	if (d <= 9)
		return "0" + d;
	return d;
}

// validation that return date is not before 

// catch up logic to change the return date when the depart date is changed
jQuery( function($) {
	$("form select[id$='_month']").change(function(){
			if ( $(this).is( "select[id^='depart']" ) )
			{
			  var this_form = $( this ).parents( "form" )[0];
			  var cal_name = $( this ).attr( "id" ).replace( '_month', '' ).replace( "depart", "return" );
			  $( "option:selected", this ).each(function () {
				 $( "#" + cal_name + "_month"  ).val( $(this).val() );
				  $("#return_day").val($("#depart_day").val());
				 getCalendar( cal_name ).monthControlChanged();
			  });		
			}
	});
	$("form select[id$='_day']").change(function(){
			if($(this).is("select[id^='depart']"))
			{
                var this_form = $(this).parents("form")[0];
                var cal_name = $(this).attr("id").replace('_day', '').replace("depart", "return");
                if($("#" + cal_name.replace("return", "depart") + "_month").val() == $("#" + cal_name + "_month").val())
                {
                    if(parseInt($(this).val()) > parseInt($("#"+cal_name.replace("depart", "return")+"_day").val()))
                    {
                        $("#" + cal_name + "_day" ).val($(this).val());
                        getCalendar(cal_name).dayControlChanged();
                    }
                }
			}
	});
	$("#depart_calendar").click( function(){
			var this_form = $( this ).parents( "form" )[0];
			depart_id = $( "table[id$='_calendar']", this_form).attr("id").replace( '_calendar', '' );
			return_id = depart_id.replace( 'depart', 'return' );
			setTimeout( 'jQuery("#' + return_id + '_month").val( jQuery("#' + depart_id + '_month").val() );  jQuery("#' + return_id + '_day").val(jQuery("#' + depart_id + '_day").val()); getCalendar("' + return_id + '").monthControlChanged();', 500 );
	});
 });
