//This javascript renders a calendar to the page. The calendar links to a database that provides
//availability data for the dates clicked on.
//The calendar can be used in the following modes:
//
//0 Show	Does db query during render and populates calendar with availability info during page render
//1 Inquire     Reports back in text which dates are free or booked.
//
//Running in Show mode causes DB access for every page load which may not be desired for high traffic pages
//Running the calendar in any other mode requires user interaction with the calendar before a DB query is made.


Date.prototype.getMonthName = function() {
	var m = ['January','February','March','April','May','June','July','August','September','October','November','December'];
	return m[this.getMonth()];
};
			
Date.prototype.getDayName = function(dayid) {
	if (dayid == null) { dayid = this.getDay() }
	var d = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
	return d[dayid];
};
			
Date.prototype.getDaysInMonth = function() {
	return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate();
};

Date.prototype.getFirstOfPrevMonth = function() {
	var prevdate = new Date(this.getTime());
	prevdate.setDate(-1);
	prevdate.setDate(1);
	return prevdate;
};
			
Date.prototype.getFirstOfNextMonth = function() {
	var nextDate = new Date(this.getTime());
	nextDate.setDate(42);
	nextDate.setDate(1);
	return nextDate;
};

Date.prototype.setDateFromMyString = function(datestring) {
	var dateparts = datestring.split('-');
	var year = parseInt(dateparts[0]);
	var month = parseInt(dateparts[1])-1;
	var day = parseInt(dateparts[2]);
	this.setFullYear(year,month,day);
};

Date.prototype.asShortString = function() {
	return this.getDate() + " " + this.getMonthName() + " " + this.getFullYear();
};

function bscalendar(name, id, dateString, mode, libraryPath){
	var self = this;
	this.name = name;
	
	if (libraryPath === undefined){
		libraryPath = '/booksheet/'; //hardcoded for compatibility with charterlink site. libraryPath should be passed in.
	}
	if (dateString == "" || dateString == null) {
		this.date = new Date();
		if (mode == "" || mode == null) { this.mode = 0; }
		else { this.mode = mode }
	}
	else {
		this.date = new Date(dateString);
		if (mode == "" || mode == null) { this.mode = 0; }
		else { this.mode = mode }
	}
	this.today = new Date();
	this.dataLoaded = false;
	this.firstDay = new Date(this.date.getFullYear(), this.date.getMonth(), 1);
	this.id = id;
	this.referenceDate = null;
	this.data = null;
	this.yesTemplate = "<span class='bsyes'>Yes!</span></br><span class='bsresponse'> &quot;%name%&quot; is available at least until</br>%endfreedate% </span><a class='bsreservationlink' href='http://www.charterlink.co.nz/index.php?option=com_content&view=article&id=157&Itemid=%id%'>Reserve here</a>";
	this.noTemplate = "<span class='bsno'>Unavailable</span></br><span class='bsresponse'> Sorry &quot;%name%&quot; is unavailable from</br>%startbookeddate% until</br>%endbookeddate%.</span>";
	this.xmlRequest = false;
	this.maxDaysReported = 7;
	this.startBookedDate = null;
	this.endBookedDate = null;
	this.startFreeDate = null;
	this.endFreeDate = null;
	this.startIndex = null;
	this.endIndex = null;
	//create calendar parent div
	var allScripts = document.getElementsByTagName('script');
       	var parent = allScripts[allScripts.length - 1].parentNode;
	this.div = document.createElement('div');
	parent.appendChild(this.div);
	this.div.className = 'bscal';
	this.parent = document.createElement('div');
	this.div.appendChild(this.parent);
	this.parent.className = 'bsinside'
	this.parent.id = this.id;       	
	this.overlay = document.createElement('div');
	this.div.appendChild(this.overlay);
	this.overlay.className = 'bsoverlay';

	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	// JScript gives us Conditional compilation, we can cope with old IE versions.
	// and security blocked creation of the objects.	
	try {
		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
		try {
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (E) {
			xmlhttp = false;
		}
	}
	@end @*/
	if (!this.xmlRequest && typeof XMLHttpRequest!='undefined') {
		try {
			this.xmlRequest = new XMLHttpRequest();
		} catch (e) {
			this.xmlRequest=false;
		}
	};
	if (!this.xmlRequest && window.createRequest) {
		try {
			this.xmlRequest = window.createRequest();
		} catch (e) {
			this.xmlRequest=false;
		}
	};	
	
	
	for (var i=0;i<730;i++){
		this.data += '0';
	};

	this.drawcalendar = function() {
		this.parent.innerHTML = '';
		var table = document.createElement('table');
		this.parent.appendChild(table);
		table.className = 'bscalendartable';
		var tbody = document.createElement('tbody');
		table.appendChild(tbody);
		var row = document.createElement('tr');
		tbody.appendChild(row);
		row.className = 'bstitlerow';
		var cell = document.createElement('td');
		row.appendChild(cell);
		
		if (this.firstDay.getTime() > (this.today.getTime() - 86400000)) {
			var prevLink = document.createElement('a');
			cell.appendChild(prevLink);
			prevLink.href = '#';
			prevLink.className = 'bsnavlinks';
			prevLink.onclick = function(){self.prevMonth(); return false;};
			var linkText = document.createTextNode('<');
			prevLink.appendChild(linkText);	
		}
		cell = document.createElement('td');
		row.appendChild(cell);		
		cell.colSpan = 5;
		var span = document.createElement('span');
		cell.appendChild(span);		
		span.className = 'bsmonthname';
		var text = document.createTextNode(this.date.getMonthName());
		span.appendChild(text);
		text = document.createTextNode(' ');
		cell.appendChild(text);	
		span = document.createElement('span');
		cell.appendChild(span);		
		span.className = 'bsyearname';
		text = document.createTextNode(this.date.getFullYear());
		span.appendChild(text);
		cell = document.createElement('td');
		row.appendChild(cell);
		var nextLink = document.createElement('a');
		cell.appendChild(nextLink);
		nextLink.href = '#';
		nextLink.className = 'bsnavlinks';
		nextLink.onclick = function(){self.nextMonth(); return false; };
		linkText = document.createTextNode('>');
		nextLink.appendChild(linkText);
		row = document.createElement('tr');
		tbody.appendChild(row);
		row.className = 'bsdaynamerow';
		for (var i=0;i<7;i++){
			cell = document.createElement('td');
			row.appendChild(cell);
			cell.className = 'bsdaynamecell';
			span = document.createElement('span');
			cell.appendChild(span);		
			span.className = 'bsdayname';
			text = document.createTextNode(this.date.getDayName(i));
			span.appendChild(text);			
		}

		var celldate = new Date(this.firstDay);
		var offset = celldate.getDay();
		var dayid = 0;
		var daysInMonth = celldate.getDaysInMonth();
		row = document.createElement('tr');
		row.className = 'bsdaterow';
		tbody.appendChild(row);
		var link = null;
		for (var i=0;i < 36;i++){
			if (dayid > 6) {
				row = document.createElement('tr');
				tbody.appendChild(row);
				row.className = 'bsdaterow';
				dayid = 0;
			}
			var oldAppearance = celldate.getTime() < (this.today.getTime() - 86400000);
			if (i >= offset && i < daysInMonth + offset){
				cell = document.createElement('td');
				row.appendChild(cell);
				
				if (!oldAppearance && this.mode > 0) {
					var link = document.createElement('a');
					link.href = '#';
				} else {
					var link = document.createElement('span');
				}
				cell.appendChild(link);
					
				var classDetail = '';
				if (this.mode == 0){
					var dateBusy = this.checkdatebusy(celldate);
					if (dateBusy == true) { classDetail = 'busy'; }
					if (dateBusy == false) { classDetail = 'free'; }
					if (dateBusy == null) { classDetail = ''; }
				} else {
					classDetail = '';
				}
				if (oldAppearance) { classDetail = 'old'; }
				link.className = 'bsdatelink' + classDetail;
				cell.className = 'bsdatecell' + classDetail;
				link.id = celldate.getFullYear() + '-' + (celldate.getMonth() + 1) + '-' + celldate.getDate();
				link.onclick = function(){self.notifyAvailability(this); return false;};
				linkText = document.createTextNode(celldate.getDate());
				link.appendChild(linkText);
				
				//increase date by one day
				celldate.setDate(celldate.getDate() + 1);				
			} else {
				var cell = document.createElement('td');
				row.appendChild(cell);
				text = document.createTextNode('\u00a0'); //equivalent to &nbsp
				cell.appendChild(text);
			}
			dayid += 1;
		}
		if (this.mode > 0){
			var footText = document.createElement('p');
			this.div.appendChild(footText);
			footText.className = 'bsfoottext';
			text = document.createTextNode('Click date to check availability');
			footText.appendChild(text);		
		}
	};
	this.nextMonth = function(){
		this.date.setDate(42);
		this.date.setDate(1);
		this.firstDay = new Date(this.date.getFullYear(), this.date.getMonth(), 1);
		this.drawcalendar();
	};
	this.prevMonth = function(){
		this.date.setDate(-1);
		this.date.setDate(1);
		this.firstDay = new Date(this.date.getFullYear(), this.date.getMonth(), 1);
		this.drawcalendar();
	};
	this.notifyAvailability = function (owner){
		switch (this.mode)
		{
			case 0: break;
			case 1: this.notifyVerbose(owner); break;
		}
	};
	
	this.checkdatebusy = function(bookDate){
		if (this.dataLoaded == false){
			this.loadData();
		}
		var index = Math.floor((bookDate.getTime() - this.referenceDate.getTime())/86400000);
		if (index > -1){
			if (this.mode == 1) { this.calcDates(index); }
			return this.data[index];
		} else {
			return null;
		}
	};
	
	this.calcIndexes = function(index){
		var dayState = this.data[index];
		this.startIndex = index;
		this.endIndex = index;
		//find state change before index
		for (var i = index; i > -1; i--){
			this.startIndex = i+1;
			if (this.data[i] != dayState) {			
				break;
			}
		}
		
		//find state change after index
		for (var i = index; i < this.data.length; i++){
			this.endIndex = i-1;
			if (this.data[i] != dayState) {
				break;
			}			
		}
		
		//apply maximum range
		if (this.maxDaysReported > -1) {
			this.startIndex = index - Math.min((index - this.startIndex), this.maxDaysReported);
			this.endIndex = index + Math.min((this.endIndex - index), this.maxDaysReported);
		}
	};
	
	this.calcDates = function(index){
		this.calcIndexes(index);
		var startDate = new Date(this.referenceDate.getTime() + (this.startIndex * 86400000));
		var endDate = new Date(this.referenceDate.getTime() + (this.endIndex * 86400000));

		if (this.data[index]){
			this.startBookedDate = startDate;
			this.endBookedDate = endDate;
			this.startFreeDate = null;
			this.endFreeDate = null;
		} else {
			this.startBookedDate = null;
			this.endBookedDate = null;
			this.startFreeDate = startDate;
			this.endFreeDate = endDate;	
		}
	};
	
	this.notifyVerbose = function(owner){
		var checkDate = new Date();
		checkDate.setDateFromMyString(owner.id);
		var dateCheck = this.checkdatebusy(checkDate);
		if (dateCheck == true) { var template = this.noTemplate; }
		if (dateCheck == false) { var template = this.yesTemplate; }
		if (dateCheck == null) { return; }

		template = template.replace(/%id%/g, this.id);
		template = template.replace(/%name%/g, this.name);
		if (this.startFreeDate != null) { template = template.replace(/%startfreedate%/g, this.startFreeDate.asShortString()); }
		if (this.endFreeDate != null) { template = template.replace(/%endfreedate%/g, this.endFreeDate.asShortString()); }
		if (this.startBookedDate != null) { template = template.replace(/%startbookeddate%/g, this.startBookedDate.asShortString()); }
		if (this.endBookedDate != null) { template = template.replace(/%endbookeddate%/g, this.endBookedDate.asShortString()); }
		this.overlay.innerHTML = template;
		//add elements and code to allow the user to close the dialog
		//todo
		var closelink = document.createElement('a');
		this.overlay.appendChild(closelink);
		closelink.href = '#';
		closelink.className = 'bscloselink';
		closelink.onclick = function(){self.closeNotify(); return false;};
		var linkText = document.createTextNode('Close');
		closelink.appendChild(linkText);						
		this.overlay.style.display = 'block';
	};
	this.closeNotify = function(){
		this.overlay.style.display = 'none';
	};
	this.loadData = function(){
		this.xmlRequest.open("GET", libraryPath + "getdata.php?id="+this.id,false);
 		this.xmlRequest.send(null);
 		var refDateString = this.xmlRequest.responseText.substring(0,10);
 		this.referenceDate = new Date(refDateString);
 		var rawbookings = this.xmlRequest.responseText.substring(11);
 		//console.log(this.xmlRequest.responseText);
 		var bookings = rawbookings.split(',');
 		//clean up array and set everything to false
 		this.data = new Array();
 		for (var i=0;i < 731; i++){ this.data[i] = 0; }
 		var index = 0;
 		var count = 0;
 		var bookitems = null;
		for (var i=0;i < bookings.length;i++){
			bookitems = bookings[i].split(':');
			index = parseInt(bookitems[0]);
			count = parseInt(bookitems[1]);
			//set the appropriate items in data array
			for (var j=0;j < count; j++){
				this.data[index + j] = 1;
			}
		}
		this.dataLoaded = true;
	};
	this.drawcalendar();
};
