	/**
	 * ---AvailabilityCalendar.js---
	 * --- Michael Cooling 27/01/09---
	 * Script to display the availability calendar of a short term rental
	 * (c) Infocasa IT, www.infocasa.com
	 * $Id: AvailabilityCalendar.js,v 1.9 2009/05/19 07:16:25 mcooling Exp $
	 */

//Change the value of this variable to 0 to be able to display weeks starting on sunday, 1 for weeks starting on monday
var firstDayOfWeek=1;							  
var allNotInRange;
var objTable;

//Main function that is called to display the rental availability calendar
function ShowAvailability(startDate,endDate,margin,checkOutSameDay,dateRanges,periodRanges,ctrlHolderName,available){
	var seasonDateRanges;
	var periodDateRanges;

	if(dateRanges==null || dateRanges.length==0){ 
		periodDateRanges=null;
		//periodDateRanges= new Array(new Array(fakeDate, fakeDate,'1400'));
	}
	else{
		periodDateRanges=eval(dateRanges);
	}
	//Build a fake array, faster than checking if array is empty
	if(periodRanges==null || periodRanges.length==0){
		//seasonDateRanges = new Array(new Array(fakeDate, fakeDate,'1400'));
		//seasonDateRanges= new Array('01/01/1980', '02/01/1980','0');
		seasonDateRanges = null;
	}
	else{
		seasonDateRanges=eval(periodRanges);
	}
	var aCal = new availabilityCalendar(startDate,endDate,margin,checkOutSameDay,periodDateRanges,seasonDateRanges,ctrlHolderName,available);
	//Draw the calendar
	aCal.draw();
}

function highLightCellTitles(el,highLight){
	if(el!=null){		
		var rw=this.document.getElementById('calAvHeaderRow');
		
		if(el.tagName=="TD"){
			if(highLight){
				el.className="calAvRowHighlight";
			}else{
				el.className="calAvRow";
			}
		}
	}
}

//Constructor
function availabilityCalendar(startDate,endDate,marginStr,checkOutSameDay,dateRanges,periodRanges,ctrlHolderName,available) {
	this.mode=true;
	this.available=(available=='true' || available==true?true:false);
	this.startDate = new Date(startDate);
	this.endDate = new Date(endDate);
	//Store the selected dates 
	this.selStartDate = new Date(startDate);
	this.selEndDate = new Date(endDate);
	
	var margin= 1*marginStr;
	//Substract  margin to start date
	this.bookingStartDate = new Date(startDate);
	this.bookingEndDate = new Date(endDate);
	this.startDate.setDate(this.startDate.getDate()-margin);
	//alert(this.startDate);
	//And now set the day to 1st
	this.startDate.setDate(1);
	
	//Add margin to enddate
	var oldMonth= this.endDate.getMonth();
	this.endDate.setDate(this.endDate.getDate()+margin);
	
	
	//And now set the day to 1st
	this.endDate.setDate(1);
	//Add a month to the result
	this.endDate.setMonth(this.endDate.getMonth()+1);
		
	this.dateRanges=GetDates(dateRanges);
	this.periodRanges=GetDates(periodRanges);
	this.seasons = getSeasons(periodRanges);
	if(dateRanges==null){
		this.dateRangesLen = 0;
	}else
	{
		this.dateRangesLen =dateRanges.length;
	}
	this.ctrlHolderName=ctrlHolderName;
	this.draw=draw;
	this.inRange=inRange;
	this.seasonClass=seasonClass;
	this.seasonRangeId=0;
	this.divsOverStartObject=null;
	this.divsOverEndObject=null;
	this.tipText='';
}

//Created a cell (TD) given a table row object
function stdCell(objRow) {
	var objCell=objRow.insertCell(objRow.cells.length);
	return (objCell);
}

//Returns the n right characters of a string
function Right(str, n){
    if (n <= 0)
       return "";
    else if (n > String(str).length)
       return str;
    else {
       var iLen = String(str).length;
       return String(str).substring(iLen, iLen - n);
    }
}

//Given a date returns
//	0 :	the date is not in a range
//	1:	the date is withen the range
//	-1:	the date is within the range and coincides with the start of the range
//	2:	the date is within the range and coincides with the end of the range
function inRange(theDate,rangeID){
	var returnVal;
	
	if (allNotInRange==true){
		return(0);
	}
	else if((this.dateRanges[rangeID][0]-theDate)==0){
		returnVal=-1;
	}
	else if((this.dateRanges[rangeID][1]-theDate)==0){
		returnVal=2;
	}
	else if(this.dateRanges[rangeID][0]<theDate && theDate<this.dateRanges[rangeID][1]){
		returnVal=1;
	}
	else{
		returnVal=0;
	}
	//alert('Returning ' + returnVal);
	return (returnVal);
}

function seasonClass(theDate){
	var returnVal;
	
	if(this.seasons==null) return ("calAvSeasonNone");
	if(this.periodRanges[this.seasonRangeId][0]<=theDate && theDate<=this.periodRanges[this.seasonRangeId][1]){
		//alert("INRANGE Date=" + theDate + " rangeID= " + this.seasonRangeId + "[" + this.periodRanges[this.seasonRangeId][0] + "," + this.periodRanges[this.seasonRangeId][1] +"]");
		switch(this.seasons[this.seasonRangeId])
		{
			case "1415":
				returnVal = "seasonPeak";
				this.tipText=seasonNames[3];
				break;
			case "1414":
				returnVal = "seasonHigh";
				this.tipText=seasonNames[2];
				break;
			case "1413":
				returnVal = "seasonMedium";
				this.tipText=seasonNames[1];
				break;
			case "1412":
				returnVal = "seasonLow";
				this.tipText=seasonNames[0];
				break;
			default:
					returnVal = "calAvSeasonNone";
					this.tipText='';
		}
	}
	else{
		//alert("OUTOFRANGE Date=" + theDate + " rangeID=" + this.seasonRangeId + " [" + this.periodRanges[this.seasonRangeId][0] + "," + this.periodRanges[this.seasonRangeId][1] + "]");

		if(this.seasonRangeId+1<this.periodRanges.length){
			if(this.periodRanges[this.seasonRangeId+1][0]-theDate==0) {
				this.seasonRangeId++;
				returnVal=this.seasonClass(theDate);
			}else
			{
				returnVal = "calAvSeasonNone";
			}
		}else{
			returnVal = "calAvSeasonNone";
		}
	}
	return (returnVal);
}


//Draws the table and inserts it into ctrlHolder on the page
function draw() {

	//Get the container div
	var objPanel = document.getElementById(this.ctrlHolderName);

	//Remove all  objects in the container object
	while (objPanel.childNodes.length > 0) objPanel.removeChild(objPanel.childNodes[0]);
	
	//Create the table object and set the dafault style
	objTable=document.createElement("table");
	objTable.input_id="calAvailabilityTable"
	objTable.className="calAvailabilityTable";
	
	//Display 5 weeks in each month row
	//Build the dow names row
	var objRow=objTable.insertRow(objTable.rows.length);
	objRow.id="calAvHeaderRow";
	var weekDayCount;
	var tmpVal = this.startDate.getDay()-firstDayOfWeek%7;
	var month_start_dow=tmpVal<0?7+tmpVal:tmpVal;
	var currentMonth = -1;
	var previousInRange = 0;
	var rangeID=0;
	var seasonRangeId=0;
	var currentDate=this.startDate;
	var className="";
	var nextInRange=0;
	var currentInRange=0;
	var maxCellsInRow=0;
	var objRowPeriods;
	var objCellPeriod;

	allNotInRange = false;
	
	//Add a cell from the month names
	var objCell=stdCell(objRow);
	
	var showRentalCalendar =  true;
	//(this.periodRanges!=null)
	
	
	//Add the week names to the row
	for(var x=0;x<37;x++){
		weekDayCount = (x+firstDayOfWeek)%7;
		objCell=objRow.insertCell(objRow.cells.length);
		objCell.className=((weekDayCount==0 || weekDayCount==6) ? "calAvWeekEndLabel":"calAvWeekDayLabel");
		objCell.innerHTML=weekDayNames[weekDayCount].substring(0,1);
	}

	//Add another row before the months
	objRow=objTable.insertRow(objTable.rows.length);
	for(x=0;x<39;x++){
		objCell=objRow.insertCell(objRow.cells.length);
		objCell.className="calAvBlankRowCell";
		objCell.innerHtml="&nbsp";
	}
	var firstMonth = true;
	
	//Goto the first availability range that is greater or equal to the current date
	if (this.dateRangesLen==0){
		//alert('length is 0');
		allNotInRange=true;
	}
	else{
		//find the first needed record
		while (currentDate>this.dateRanges[rangeID][1] && rangeID<this.dateRangesLen) rangeID++;
		//alert('Finished while rangeID=' + rangeID);
		if (rangeID==this.dateRangesLen){
			//alert('Finished setting allNotInRange=true');
			if(currentDate>this.dateRanges[rangeID][1]) allNotInRange=true;
		}
	}
	

	//Add a new row for the month when the month changes and fill in all the cells to the end of the current row
	while (currentDate.getMonth() != currentMonth && currentDate<this.endDate){
		//If we need to diplay another month then set all the needed values and add a row to the table
		if(this.endDate>=currentDate){

			
			//Set the current month to this month;
			currentMonth = currentDate.getMonth();
			if (showRentalCalendar){
				//Add a blank row 
				objRowPeriods = objTable.insertRow(objTable.rows.length);
				objRowPeriods.className = "calAvSeparatorRow";
				for(x=0;x<39;x++){
					objCellPeriod=objRowPeriods.insertCell(objRowPeriods.cells.length);
					objCellPeriod.className="calAvailEmpty";
					objCellPeriod.innerHtml="&nbsp";
				}
				//Add a row for the seasonRanges
				objRowPeriods = objTable.insertRow(objTable.rows.length);
				objRowPeriods.className='calAvSeasonsRow';
			}
			//Add a new row for the currentMonth
			objRow=objTable.insertRow(objTable.rows.length);
			objRow.className="calAvRow";

			//Add cell with month name
			objCell=stdCell(objRow);

			//add event handlers to the cell
			objCell.className="calAvMonthNameLabel";
			objCell.innerHTML=monthNames[currentMonth] + " " + Right(currentDate.getYear(),2);
			if (showRentalCalendar){
				//Add a row for the seasonRanges
				objCellPeriod=stdCell(objRowPeriods);
				//objCellPeriod.className="calAvMonthNameLabel";
			}
			//Find the firs DOW of the current month
			tmpVal = currentDate.getDay()-firstDayOfWeek%7;
			currentMonth = currentDate.getMonth();
			month_start_dow=tmpVal<0?7+tmpVal:tmpVal;
			//Write the empty cells before the month start
			for(x=0;x<month_start_dow;x++){
				//Add the period cells if needed 
				if (showRentalCalendar) {
					objCellPeriod=stdCell(objRowPeriods);
					objCellPeriod.className="calAvailEmpty";
				}
				objCell=stdCell(objRow);
				objCell.className="calAvailEmpty";
			}
			//Write the whole month depending on the occupation for this month
			while(currentDate.getMonth() == currentMonth){
				
				if (showRentalCalendar) {
					objCellPeriod=stdCell(objRowPeriods);
					objCellPeriod.className= "calAvSeason " + this.seasonClass(currentDate);
					if(this.tipText.length>0) objCellPeriod.title="(" + this.tipText +")";
				}
				
				//Create the td cell with mouseover and mouseout events
				objCell=stdCell(objRow);
				objCell.className="calAvDateCell";
				objCell.onmouseover=new Function("checkHighlight(this,true)");
				objCell.onmouseout=new Function('checkHighlight(this,false)');
				
				//Store start and end cells that define the booking
				if(this.bookingStartDate.toString()==currentDate.toString()){
					this.divsOverStartObject=objCell;
				}
				if(this.bookingEndDate.toString()==currentDate.toString()){
					this.divsOverEndObject=objCell;
				}
				
				//alert(objTable.rows[objTable.rows.length-1].cells[objCell.cellIndex].style.borderBottom);
				if (objTable.rows[objTable.rows.length-1].cells[objCell.cellIndex].style.borderBottom=="") objCell.className=objCell.className + " calAvNoCellAbove";
				
				switch(this.mode){
					case false: //we could code this node if we just wanted a seasons calendar
						objCell.className=this.seasonClass(currentDate);
						break;
					default:
					
						currentInRange=this.inRange(currentDate,rangeID)
						var concatClass = ((currentDate.getDay()==0 || currentDate.getDay()==6)?"WeekEndDay":"WeekDay");
						switch(currentInRange){
							case -1:
								//Start of left hand side
								//if the previous one was the end and this one is a start then wee will set the availability as fully occupied
								//Check if the next range start for this date is the begining, if so then
								if(rangeID>0){
									className=(this.inRange(currentDate,rangeID-1)==2?"calAvNo":"calAvNoStart") + concatClass;
								}else{
									className="calAvNoStart" + concatClass;
								}
								className=className + " calAvAvailable" + concatClass;
								break;
							case 0:
								//no coincidence
								//if we are at a currentDate that is grater than the current range we will move on to the next range
								if (this.dateRangesLen>0){
								if(currentDate>this.dateRanges[rangeID][1]) {
									//Set the current date range to the next one
									if(rangeID==this.dateRangesLen-1){
										allNotInRange=true;
									}
									else{
										rangeID+=1;
									}
								}
								}
								className="calAvAvailable"+ concatClass;
								break;
							case 1:
								//coincidence
								className="calAvNotAvailable"+ concatClass;
								break;
							case 2:
								
								//Need to check if the next date range is available or not to display a complete red square
								if(rangeID<this.dateRangesLen-1){
									className=((this.inRange(currentDate,rangeID+1)==-1 || this.inRange(currentDate,rangeID+1)==1)?"calAvNotAvailable":"calAvAvailable" + concatClass + " calAvNoEnd")+ concatClass;
								}else{
										className="calAvNoEnd"+ concatClass;
										className=className + " calAvAvailable" + concatClass;
								}
								break;
						}
						//Set the cell className
						objCell.className = objCell.className + " " + className;
						//If the cell is a start or end cell, check the next cell
						if (className.indexOf("NoEnd")>0 || className.indexOf("NoStart")>0){
							objDiv=BuildDiv(objCell,currentDate.getDate());
						}
						else{
							objCell.innerHTML=currentDate.getDate();
						}
						
						//Set the style for the selected date range
						//alert(this.selStartDate + " <= " + currentDate + ' =>' + this.selEndDate);
						if (this.available && this.selStartDate<=currentDate && currentDate<=this.selEndDate){
							objCell.className=objCell.className + " calAvSelection" + concatClass;
						}
						
						objCell.title=currentDate.getDate() + " " + monthNames[currentMonth] + " " + Right(currentDate.getYear(),2);
						if (showRentalCalendar && this.tipText.length>0) {
							objCell.title=objCell.title + " (" + this.tipText + ")";
						}
						//Have we finished with the current date range?
						if(currentInRange==2){
							
							//Set the current date range to the next one
							if(rangeID==this.dateRangesLen-1){
								allNotInRange=true;
							}
							else{
								rangeID+=1;
							}
						}
						break;
				}
				currentDate.setDate(currentDate.getDate()+1);
			}
			objCell.className=objCell.className + " calAvNoCellRight";
			//Write the normal cells until the end of the month previous month
			for(x=objRow.cells.length+1;x<39;x++){
				objCell=stdCell(objRow);
				objCell.className="calAvailEmpty";
				objCell.innerHtml="&nbsp";
				objCell=stdCell(objRowPeriods);
				objCell.className="calAvailEmpty";
				objCell.innerHtml="&nbsp";
			}
		}
		firstMonth = false;
	}
	
	//Append the table to the panel div
	objPanel.appendChild(objTable);
	
	var objOldTable=objTable;
	//Add another table to hold the legend
	objTable= document.createElement("table");
	objTable.className="calLegendTable";
	objRow = objTable.insertRow(objTable.rows.length);
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvNotAvailableWeekDay";
	objCell.innerHTML="1";
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvNotAvailableWeekEndDay";
	objCell.innerHTML="2";
	
	objCell = stdCell(objRow);
	objCell.className= "calLegendLabel";
	objCell.innerHTML=bookedText;
	
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvAvailableWeekDay";
	objCell.innerHTML="1";
	
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvAvailableWeekEndDay";
	objCell.innerHTML="2";
	
	objCell = stdCell(objRow);
	objCell.className= "calLegendLabel";
	objCell.innerHTML=availableText;
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvSelectionWeekDay";
	objCell.innerHTML="1";
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvSelectionWeekEndDay";
	objCell.innerHTML="1";
	
	objCell = stdCell(objRow);
	objCell.className= "calLegendLabel";
	objCell.innerHTML=selectionText;
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvNoStartWeekEndDay calAvAvailableWeekEndDay";
	BuildDiv(objCell,1);
	
	objCell = stdCell(objRow);
	objCell.className="calAvDateCell calAvNoCellAbove calAvNoEndWeekEndDay calAvAvailableWeekEndDay";
	BuildDiv(objCell,2);
	
	objCell = stdCell(objRow);
	
	objCell.className= "calLegendLabel";
	objCell.innerHTML=checkInOutText;
	
	
	
	//Append the table to the panel div
	objPanel.appendChild(objTable);
	
	objTable=objOldTable;
	//Display the div container
	objDiv=document.getElementById("ssRentalAvailabilityCalendar");
	if (objDiv!=null) objDiv.style.display="block";
	
}

//Converts the first two elements of a string array into a new array of date ranges
function GetDates(sourceArray){
	var resultArray=new Array();
	var range;
	if (sourceArray==null){
		return null;
	}
	
	var ub=sourceArray.length;

	for (var i=0;i<ub;i++){
		resultArray[i]= new Array(new Date(sourceArray[i][0]),new Date(sourceArray[i][1]));
	}
	
	return resultArray;
	
}

function getSeasons(sourceArray){
	var resultArray=new Array();
	var range;
	
	if (sourceArray==null){
		return null;
	}
	var ub=sourceArray.length;
	for (var i=0;i<ub;i++){
		resultArray[i]= sourceArray[i][2];
	}
	return resultArray;
}


//Adds class name to the 
function checkHighlight(el,which) {

	if (el.tagName=="TD"){
		var index = el.cellIndex;
		el = el.parentNode;
	}
	
    if (el==null) return;
	
	if (which){
		for(i=0;i<el.cells.length;i++){
			el.cells[i].className='highlight ' + el.cells[i].className  ;
		}
		objTable.rows[0].cells[index].className = 'highlight ' + objTable.rows[0].cells[index].className;
		objTable.rows[1].cells[index].className = 'highlight ' + objTable.rows[1].cells[index].className;
		for(i=2;i<el.rowIndex;i++){
			if (objTable.rows[i].cells[index].className.indexOf('calAvailEmpty')>=0) objTable.rows[i].cells[index].className = 'highlight ' + objTable.rows[i].cells[index].className;
		}
	}else{
		for(i=0;i<el.cells.length;i++){
			el.cells[i].className=el.cells[i].className.replace('highlight ','');
		}
		objTable.rows[0].cells[index].className = objTable.rows[0].cells[index].className.replace('highlight ','');
		objTable.rows[1].cells[index].className = objTable.rows[1].cells[index].className.replace('highlight ','');
		for(i=2;i<el.rowIndex;i++){
			if (objTable.rows[i].cells[index].className.indexOf('calAvailEmpty')>=0) objTable.rows[i].cells[index].className=objTable.rows[i].cells[index].className.replace('highlight ','');
		}
		
	}
}

function BuildDiv(objCell,date){
	var objDiv;
	var objDiv2;
	//Create the divs that will hold a drawn tringle and the day text on top
	objDiv=document.createElement("div");
	objDiv.className="calAvSpitCellContainer";

	objDiv2=document.createElement("div");
	objDiv2.className=objCell.className;
	objDiv.appendChild(objDiv2)
	
	objDiv2=document.createElement("div");
	objDiv2.className="calAvSpitCellText";
	objDiv2.innerHTML='<p style=" position: relative;">' + date + '</p>';
	objDiv.appendChild(objDiv2);
	objCell.appendChild(objDiv);
	return objDiv;
}
