function yearView (year, propType, monthsDataStr)
// Build a yearView obj for given year and display it
// Fetch seasonal information from server
{
	this.yrSelId = 'clsYrSel';
	this.year = year;
	this.weekdays = new Array ('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'); 
	this.months = new Array ('January','February','March','April','May','June','July','August','September','October','November','December');

	// Month data contains 12 strings each with one digit for every day in the month
	// The digits are: 0: low season, 1: mid season, 2: high season, 3: peak season
	this.monthsData = new Array();
	this.monthsData = this.monthsData.concat (monthsDataStr);
	this.propType = propType;

}

yearView.prototype.cellColrs = new Array ('#99BCFF', '#FFF081', '#FFAA11', '#EA75D6');

yearView.prototype.buildControl = function () 
// Build the year selector.
{
	var buf = new writer();
	buf.into ('<table><tr><td style="width:100px">', this._getYrSelectorHtml (), 
					'</td><td style="width:570px">', this._getPropTypeSelHtml (), 
					'</td></tr><tr><td style="width:100px">&nbsp;</td><td align="right">', this._getKeyHtml (), 
					'</td></tr></table><br clear="all" />'); 
	document.write(buf.out());
}

yearView.prototype.buildYearView = function  ()
{
	document.write ('<span name="YearGrid" id="YearGrid">');
	document.write (this._getYearGrid ());
	document.write('</span>');
}

yearView.prototype.initGridEvents = function (dayClickFn)
{
	// Set the event handler for each cell
	var day, mon, maxDays, cell, cellId;
	
	for (mon = 0; mon < 12; mon++)
	{
		maxDays = getDaysInMon (mon, this.year);
		for (day = 1; day <= maxDays; day++)
		{
			cellId = "Cell" + padNum (mon) + padNum (day);
			cell = getObject (cellId);
			cell.onclick = dayClickFn;
		}
	}
}

yearView.prototype.updateGrid = function (dayClickFn)
{
	var yearGrid = getObject("YearGrid");
	yearGrid.innerHTML = '&nbsp;';
	yearGrid.innerHTML = this._getYearGrid ();
	this.initGridEvents (dayClickFn);
}

yearView.prototype._getYearGrid = function ()
{
	var mon;
	var buf = new writer();
	buf.into ('<table><tr>');
	for (mon = 0; mon < 12; mon++)
	{
		buf.into (this._getMonthView (mon));
//		if ((mon == 2) || (mon == 5) || (mon == 8))
		if ((mon == 3) || (mon == 7))
			buf.into ('</tr><tr>');
	}
	buf.into ('</tr></table>');
	return buf.out();
}

yearView.prototype._getMonthView = function (mon)
// Build the given month View & return it
{
	var buf = new writer();
	buf.into ('<td style= "vertical-align: top"><div style="background-color:white; width:165px; height:175px">',
						'<table  width="100%" cellpadding="0px" cellspacing="1px" border="0px" class="clsOuterFrame">',
						'<tr><td ><table width="100%" cellpadding="0px" cellspacing="0px" border="0px" class="clsInnerFrame">',
						'<tr><td colspan="3" class="clsTopPartNavpanel">',
						'<img src="../assets/Cal/spacer.gif" width="1px" height="1px" /></td></tr>',
						'<tr><td width="100%" colspan="3"><table cellpadding="1px" cellspacing="1px" border="0px" style="width:163px">',
						'<tr><td width="100%" class="clsInfoTitle">', 
						this.months[mon], '&nbsp;',
						'</td></tr></table></td></tr><tr><td colspan="3" class="clsBottomPartNavpanel">',
						'<img src="../assets/Cal/spacer.gif" width="1 px" height="1 px"></td></tr><tr class="clsMidRow">',
						'<td><img src="../assets/Cal/spacer.gif"  width="4 px"height="1 px"></td>',
						'<td align="center" >',	this._getGridHtml(mon), 
						'</td><td width="4px"><img src="../assets/Cal/spacer.gif"  width="4px" height="1px"></td></tr>',
						'<tr><td colspan="3" class="clsBottomPartNavpanel">',
						'<img src="../assets/Cal/spacer.gif" width="1 px" height="1 px" /></td></tr></table></td ></tr></table></div></td>');

	return buf.out();
}

yearView.prototype._getYrSelectorHtml = function ()
// Return the HTML for the year selector
{
	var yr, reqYr, buf = new writer();

	var today = new Date ();
	var thisYr = today.getFullYear();
	reqYr = this.year;

	buf.into ('Year: <select name= "', this.yrSelId, '" id= "', this.yrSelId, '" onChange="changeYear(this)">');
	
	for (yr = thisYr; yr <= (thisYr + 10); yr++)
	{
		buf.into ('<option value= "', yr, '"');
		if (yr == reqYr)
			buf.into (' selected = "selected"');
		buf.into ('>', yr, '</option>');
	}

	buf.into ('</select>');
	return (buf.out());
}

yearView.prototype._getPropTypeSelHtml = function ()
// Return the HTML for the property type selector
{
	var i, propType, reqPropType, buf = new writer();

	reqPropType = this.propType;

	var propTypeVals = new Array ("", "Villa", "Condo");
	var propTypeValsLen = propTypeVals.length;
	buf.into ('Property type: <select name= "PropType" id= "PropType" onChange="changePropType(this)">');
	for (i = 0; i < propTypeValsLen; i++)
	{
		propType = propTypeVals[i];
		buf.into ('<option value= "', propType, '"');
		if (propType == reqPropType)
			buf.into (' selected = "selected"');
		buf.into ('>', propType, '</option>');
	}

	buf.into ('</select>');
	return (buf.out());
}

yearView.prototype._getKeyHtml = function ()
{
	var html = '<b>Key:-</b> &nbsp;&nbsp;&nbsp;Low season: <img src="../assets/PageAssets/LoSeasonKey.jpg" /> ' + 
						'&nbsp;&nbsp;&nbsp;&nbsp;Mid season: <img src="../assets/PageAssets/MidSeasonKey.jpg" /> ' +
						'&nbsp;&nbsp;&nbsp;&nbsp;High season: <img src="../assets/PageAssets/HiSeasonKey.jpg" /> ' +
						'&nbsp;&nbsp;&nbsp;&nbsp;Peak season: <img src="../assets/PageAssets/PkSeasonKey.jpg" />';
	return html;
}

yearView.prototype._getGridHtml = function (mon)
// Return the HTML for the table containing the day names & the grid of dates
{
	var buf = new writer();
	buf.into ('<table cellpadding="2" cellspacing="1" border="0" width="100%" class="clsDateGrid">');
	buf.into (this._getDaysHtml());
	buf.into (this._getDateGridHtml(mon));
	buf.into ('</table>');
	return (buf.out());
}

yearView.prototype._getDaysHtml = function ()
// Return the HTML code for a table row containing 7 cells each with the name of a day of the week
{
	var buf = new writer();
	buf.into('<tr  class="clsWeekDay">');
	for (var wkDay = 0; wkDay < 7; wkDay++) 
		buf.into('<td style="width:10px; font: bold 9px Verdana, Arial Narrow, sans-serif">', 
							this.weekdays[(wkDay + 1) % 7], '</td>');

	buf.into('</tr>');
	return(buf.out());
}

yearView.prototype._getDateGridHtml = function (mon)
// Return the html for the grid of dates
{
	var buf = new writer();
	var firstDay = new Date();
	firstDay.setDate(1);
	firstDay.setMonth(mon);
	firstDay.setYear(this.year);
	firstDay.setDate(1 - ((6 + firstDay.getDay()) % 7));
	var currDay = new Date(firstDay);
	while ((currDay.getMonth() == mon) || (currDay.getMonth() == firstDay.getMonth())) 
	{
		buf.into('<tr>');
		for (var wkDay = 0; wkDay < 7; wkDay++) 
		{
			buf.into(this._getDayCellHtml(currDay, mon));
			currDay.setDate(currDay.getDate() + 1);
		}
		buf.into('</tr>\n');
	}
	return(buf.out());
}

yearView.prototype._getDayCellHtml = function (inDate, mon) 
// Get the HTML for the yearView cell with the given date
{
	var sLink, cellHtml;
	var day = inDate.getDate ();
	var year = this.year;
	var dataStr = new String(this.monthsData[mon]);
	var dateState = dataStr.charAt(day - 1);
	var dateType = this._getDateType (mon, year, inDate);

	var classId = this._getClassId (dateType, dateState);

	var availableId = "availableDay";

	var cellIdTxt = "";
	if (dateType & 8)
		cellHtml = "&nbsp;";
	else
	{
		cellHtml = inDate.getDate();
		var cellId = "Cell" + padNum (mon) + padNum (day);
		cellIdTxt = 'name="' + cellId + '" id="' + cellId + '"';
	}

	cellHtml = '<td class="' + classId + '" align="center"' + cellIdTxt + '>' + cellHtml + '</td>';
	return cellHtml;
}

yearView.prototype._getDateType = function (mon, year, inDate) 
// Return the type of date as a 4 bits:
// Bit 1 always set, bit 2 is not set
// Bit 3 set if this is Sat or Sun, bit 4 set if this day is not in the current month
{
	var nResType = 1, tmpDate = new Date(inDate);
var tmpMon = tmpDate.getMonth();
	if ((tmpDate.getMonth() != mon) || (tmpDate.getFullYear() != year))	
		nResType |= 8;
	if ((tmpDate.getDay() == 0) || (tmpDate.getDay() == 6))	
		nResType |= 4;
	return nResType;
}

yearView.prototype._getClassId = function (dateType, dateState)
{
	var classId;
	
	if (dateType & 8) 
		classId = 'none';
	else
	{
		if (dateState == 0) 
			classId = 'loSea';
		else if (dateState == 1)
			classId = 'midSea';
		else if (dateState == 2) 
			classId = 'hiSea';
		else if (dateState == 3) 
			classId = 'pkSea';
	}
	return classId;
}

yearView.prototype._fillMonthsData = function (monthsDataStr)
{
	// Fill an array with month arrays each containing an integer for each day that represents its status
	// monthsDataStr is an array of strings where each character is this same integer

	var monthsData = new Array(12);
	for (var i = 0; i < 12; i++)
	{
//		var mon !!!!KEEP AS STRINGS!!!!
		monthsData[i] = monthsDataStr[i].split ("");
	}

	return monthsData;
}

// ------------------------------------------------------------------------------------------
// Availability object
// ------------------------------------------------------------------------------------------

function availability (year, property, monthsDataStr)
{
	this.property = property;

	this.base = yearView;
	this.base (year, "villa", monthsDataStr);
}

availability.prototype = new yearView();
availability.prototype.cellColrs = new Array ('#99BCFF', '#FFAA11');

availability.prototype.buildControl = function (propList) 
// Build the year selector.
{
	var buf = new writer();
	buf.into ('<table><tr><td style="width:100px">', this._getYrSelectorHtml (), 
					'</td><td style="width:570px">', this._getPropSelHtml (propList), 
					'</td></tr><tr><td style="width:100px">&nbsp;</td><td align="right">', this._getKeyHtml (), 
					'</td></tr></table><br clear="all" />'); 
	document.write(buf.out());
}

availability.prototype._getPropSelHtml = function (propList)
// Return the HTML for the property selector
{
	var i, property, reqProperty, buf = new writer();

	reqProperty = this.property;

	var propListLen = propList.length;
	buf.into ('Property: <select name= "Property" id= "Property" onChange="changeProperty(this)">');
	for (i = 0; i < propListLen; i++)
	{
		property = propList[i];
		buf.into ('<option value= "', property, '"');
		if (property == reqProperty)
			buf.into (' selected = "selected"');
		buf.into ('>', property, '</option>');
	}

	buf.into ('</select>');
	return (buf.out());
}

availability.prototype._getKeyHtml = function ()
{
	var html = '<b>Key:-</b> &nbsp;&nbsp;&nbsp;Available: <img src="../assets/PageAssets/LoSeasonKey.jpg" /> ' + 
						'&nbsp;&nbsp;&nbsp;&nbsp;Booked: <img src="../assets/PageAssets/HiSeasonKey.jpg" />';
	return html;
}

availability.prototype._getClassId = function (dateType, dateState)
{
	var classId;
	
	if (dateType & 8) 
		classId = 'none';
	else
	{
		if (dateState == 0) 
			classId = 'loSea';
		else if (dateState == 1)
			classId = 'hiSea';
	}
	return classId;
}

// ------------------------------------------------------------------------------------------
// AvailabilityView object
// ------------------------------------------------------------------------------------------

function availabilityView (year, property, monthsDataStr)
{
	this.property = property;

	this.base = availability;
	this.base (year, property, monthsDataStr);
}

availabilityView.prototype = new availability();

availabilityView.prototype.buildControl = function () 
// Build the year selector.
{
	var buf = new writer();
	buf.into ('<table><tr><td style="width:100px">', this._getYrSelectorHtml (), 
					'</td><td style="width:570px">&nbsp;',  
					'</td></tr><tr><td style="width:100px">&nbsp;</td><td align="right">', this._getKeyHtml (), 
					'</td></tr></table><br clear="all" />'); 
	document.write(buf.out());
}

// ------------------------------------------------------------------------------------------
// General functions
// ------------------------------------------------------------------------------------------

function getDaysInMon (mon, year)
{
	// Return the number of days in the given month and year
	var maxDays;
	var monLengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	
	if ((mon == 1) && ((year % 4) == 0))
		return 29;		// It's Feb in a leap year
	else
		return monLengths[mon];
}

function padNum (num)
{
	// Pad the given number to two digits
	numStr = num.toString();
	if (numStr.length == 1)
		numStr = "0" + numStr;
	
	return numStr;
}

function writer() 
// Object for concatenating strings
// Feed it a series of strings using the "into" method N.B. this takes a variable number of arguments
// Retrieve them concatenated using the "out" method
{
	this.bufArray = [];
	this.into = function () 
	{
		var n = arguments.length;
		for (var i = 0; i < n; i++)
			this.bufArray[this.bufArray.length] = arguments[i];
	};

	this.out = function () 
	{
		return this.bufArray.join('');
	};
}

