/*
	Javascript code written by PSLWeb.co.uk. Copyright ©2011 PSLWeb.co.uk - All Rights Reserved.
*/
/*
	Function:    setFocus
	Called From: BODY Element (if set)
	Inputs:		 fieldIdfr: Integer - an identifier denoting a specific form field Label.
	Output:		 None.
	Description: Sets the form focus to a form field identified via the field identifier (fieldIdfr).
*/
function setFocus(fieldIdfr) {
	userForm = document.getElementById('bookingForm');
	switch (fieldIdfr) {
		case 1:
			userForm.holiday.focus();
			break;
		case 2:
			userForm.cottage.focus();
			break;
		case 3:
			userForm.day.focus();
			break;
		case 4:
			userForm.nights.focus();
			break;
		case 5:
			userForm.title.focus();
			break;
		case 6:
			userForm.initial.focus();
			break;
		case 7:
			userForm.surname.focus();
			break;
		case 8:
			userForm.addr1.focus();
			break;
		case 9:
			userForm.addr2.focus();
			break;
		case 10:
			userForm.city.focus();
			break;
		case 11:
			userForm.county.focus();
			break;
		case 12:
			userForm.postcode.focus();
			break;
		case 13:
			userForm.country.focus();
			break;
		case 14:
			userForm.email.focus();
			break;
		case 15:
			userForm.teleD.focus();
			break;
		case 16:
			userForm.teleE.focus();
			break;
		case 17:
			userForm.teleM.focus();
			break;
		case 18:
			userForm.cot.focus();
			break;
		case 19:
			userForm.highchair.focus();
			break;
		case 20:
			userForm.dog.focus();
			break;
		case 21:
			userForm.heard.focus();
			break;
		case 22:
			userForm.terms.focus();
			break;
		default:
			userForm.holiday.focus();
			break;
	}
};

/*
	Function:    restoreCottages
	Called From: holidayChange
	Inputs:		 thisForm: Object - the HTML form (bookingForm).
				 cottage_id: Integer - the originally selected cottage that we wish to set as default
				 			when we restore the full cottage list in the pull-down menu.
	Output:		 None.
	Description: Restores all the cottage options in the cottage pull-down menu and defaults to the
					original cottage selected when the form was first displayed. This function is called
					when we select a 'standard' holiday. E.g. We may have selected a 'special' which
					reduces the list of cottages in the pull-down menu (because some specials are only
					available to certain cottages), therefore if we revert to a standard holiday we need
					to restore the cottage list.
*/
function restoreCottages(thisForm, cottage_id) {
	// The following two lines caused an infinte loop in IE9
	//while (thisForm.cottage.options.length) // Remove all existing SELECT OPTIONS
	//	thisForm.cottage.options[0] = null;
	// The following four lines are the fixed version
	//var cottages = thisForm.cottage.options.length;
	//for (var i = 0; i < cottages; i++)
	//	thisForm.cottage.options[0] = null;
	//thisForm.cottage.options.length = 0;
	while (thisForm.cottage.firstChild)
		thisForm.cottage.removeChild(thisForm.cottage.firstChild);
	thisForm.cottage.options[0] = new Option("The Butler's Pantry", 1, (cottage_id == 1), (cottage_id == 1));
	thisForm.cottage.options[1] = new Option("The Old Pump House", 2, (cottage_id == 2), (cottage_id == 2));
	thisForm.cottage.options[2] = new Option("Sam's Stable", 3, (cottage_id == 3), (cottage_id == 3));
	thisForm.cottage.options[3] = new Option("The Old Coach House", 4, (cottage_id == 4), (cottage_id == 4));
};

/*
	Function:    holidayChange
	Called From: Booking Form (holiday field onchange event)
	Inputs:		 cottage_id: Integer - the originally selected cottage that we may wish to set as default
				 			if we restore the full cottage list in the pull-down menu.
	Output:		 None.
	Description: Alters the Date, Night and Cottage fields values depending on the holiday selected.
					If a standard holiday is selected then we set the nights (weekly and fortnightly only)
					and restore the full cottage list. If a special is selected then we use the data in
					hidden form fields to set the date, nights and available cottages accordingly.
*/
function holidayChange(cottage_id) {
	var cottage_id = parseInt(cottage_id, 10);
	var thisForm = document.getElementById('bookingForm');
	var holidaySelected = thisForm.holiday.value;
	switch (holidaySelected) {
		case 'week':
			thisForm.nights.value = 7;
			restoreCottages(thisForm, cottage_id);
			break;
		case 'fortnight':
			thisForm.nights.value = 14;
			restoreCottages(thisForm, cottage_id);
			break;
		case 'other':
			restoreCottages(thisForm, cottage_id);
			break;
		default:
			var specDate = 's' + holidaySelected + 'd';
			var specNights = 's' + holidaySelected + 'n';
			var specCottages = 's' + holidaySelected + 'c';
			var thisDate = thisForm[specDate].value;
			var thisNights = thisForm[specNights].value;
			var thisCottages = thisForm[specCottages].value;
			var dayVal = parseInt(thisDate.substr(8, 2), 10);
			var monthVal = parseInt(thisDate.substr(5, 2), 10);
			var yearVal = parseInt(thisDate.substr(0, 4), 10);
			thisForm.day.value = dayVal;
			thisForm.month.value = monthVal;
			thisForm.year.value = yearVal;
			thisForm.nights.value = parseInt(thisNights, 10);
			//while (thisForm.cottage.options.length) // Remove all existing SELECT OPTIONS
			//	thisForm.cottage.options[0] = null;
			//thisForm.cottage.options.length = 0;
			while (thisForm.cottage.firstChild)
				thisForm.cottage.removeChild(thisForm.cottage.firstChild);
			var i = 0;
			if (thisCottages.substr(0, 1) == 'Y')
				thisForm.cottage.options[i++] = new Option("The Butler's Pantry", 1, (cottage_id == 1), (cottage_id == 1));
			if (thisCottages.substr(1, 1) == 'Y')
				thisForm.cottage.options[i++] = new Option("The Old Pump House", 2, (cottage_id == 2), (cottage_id == 2));
			if (thisCottages.substr(2, 1) == 'Y')
				thisForm.cottage.options[i++] = new Option("Sam's Stable", 3, (cottage_id == 3), (cottage_id == 3));
			if (thisCottages.substr(3, 1) == 'Y')
				thisForm.cottage.options[i++] = new Option("The Old Coach House", 4, (cottage_id == 4), (cottage_id == 4));
			//work out if it is a leap year
			var IsLeap = !(yearVal % 4) && ((yearVal % 100) || !(yearVal % 400));
			//find the number of days in that month
			var daysInMonth = [31, (IsLeap ? 29 : 28), 31, 30 , 31, 30, 31, 31, 30, 31, 30, 31][monthVal - 1];
			//store the current day - reduce it if the new month does not have enough days
			var storedDate = (dayVal > daysInMonth) ? daysInMonth - 1 : dayVal - 1;
			while (thisForm.day.firstChild)
				thisForm.day.removeChild(thisForm.day.firstChild);
			for (var i = 0; i < daysInMonth; i++)
				thisForm.day.options[i] = new Option(i + 1, i + 1); 
			thisForm.day.options[storedDate].selected = true; //select the number that was selected before
			break;
	}
};

/*
	Function:    nightsDateChange
	Called From: Booking Form (nights field onchange event)
				 calendar_popup.js (datePickerReturn function)
	Inputs:		 None.
	Output:		 None.
	Description: Alters the holiday value depending on the values of the date and nights fields. The
					values set are given in the switch statement.
*/
function nightsDateChange() {
	var bookingForm = document.getElementById('bookingForm');
	var day = parseInt(bookingForm.day.value, 10);
	var month = parseInt(bookingForm.month.value, 10) - 1; // Months go from 0 - 11 (for the Date method)
	var year = parseInt(bookingForm.year.value, 10);
	var thisDate = new Date(year, month, day); // Date as selected on the form
	var isSat = (thisDate.getDay() == 6); // TRUE if this date is a Saturday, FALSE otherwise
	var nights = parseInt(bookingForm.nights.value, 10);
	switch (nights) {
		case 7:
			bookingForm.holiday.value = (isSat) ? 'week' : 'other';
			break;
		case 14:
			bookingForm.holiday.value = (isSat) ? 'fortnight' : 'other';
			break;
		default:
			bookingForm.holiday.value = 'other';
	}
};


var HTTP = {}; // This is the Global Object containing all the HTTP (AJAX) functions

/*
	Function:    HTTP.newRequest
	Called From: HTTP.post
	Inputs:		 None.
	Output:		 Object - An XMLHttpRequest object if one can be allocated, else FALSE.
	Description: Tries to allocate a new XMLHttpRequest object (browser dependent). If it fails to
					allocate any it returns FALSE.
*/
HTTP.newRequest = function() {
	var http_request = false;
	if (window.XMLHttpRequest) // Modern Browsers
		http_request = new XMLHttpRequest();
	else if (window.ActiveXObject) { // IE
		try {
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}
	return http_request;
};

/*
	Function:    HTTP.encodeFormData (based on JavaScript - The Definitive Guide)
	Called From: HTTP.post
	Inputs:		 data: Object - parameter list (encoded as object properties and values).
	Output:		 String - A URI encoded list of the input parameter list. Nb: spaces are encoded as '+'
					in accordance to the POST form encoding standard (application/x-www-form-urlencoded).
	Description: Takes a parameter list encoded as an object (propery and values) and converts is to
					a (URI encoded) string which can be POSTed to the server.
*/
HTTP.encodeFormData = function(data) {
	var pairs = [];
	regexp = new RegExp("\\%20", 'g'); // A regular expression to match an encoded space
	for (var name in data) {
		var value = data[name].toString();
		var pair = encodeURIComponent(name).replace(regexp, '+') + '=' +
				encodeURIComponent(value).replace(regexp, '+');
		pairs.push(pair);
	}
	return pairs.join('&'); // Concatenate all the name/value pairs, separating them with an ampersand
};

/*
	Function:    HTTP.showResult
	Called From: HTTP.post
	Inputs:		 response: Object - Contains the following three properties:
					errMsg: String - Contains the error message (if an error), else is empty.
					fieldIdfr: String - An identifier denoting which form field is in error. If there is
							no error then this is empty. This field may be omitted.
					price: Integer - The Price if one is calculated. This may be omitted or zero.
	Output:		 None.
	Description: Takes a 'response' object and shows output to the User. It may show an error or the
					calculated price. Form label classes and text output classes are set/reset accordingly.
*/
HTTP.showResult = function(response) {
	var obj;
	var errMsg = (response.errMsg) ? response.errMsg : "";
	var fieldIdfr = (response.fieldIdfr) ? response.fieldIdfr : "";
	var price = (response.price) ? response.price : "";
	var responseText = document.getElementById('responseText'); // This is where our text is to go
	if (errMsg != "") { // There is a Booking Form Error
		responseText.className = 'error';
		responseText.innerHTML = errMsg;
		obj = document.getElementById('label' + fieldIdfr); // Get the Label for the field in error
		if (obj)
			obj.className = "error"; // Set Label class to 'error'
	}
	else { // No error, so show the price
		responseText.className = 'checkPriceOK';
		responseText.innerHTML = 'Cottage available for &pound;' + price;
	}
};

/*
	Function:    HTTP.post (based on JavaScript - The Definitive Guide)
	Called From: bookingForm button 'Check availability and price'
	Inputs:		 url: String - the AJAX URL to call (this is booking.php).
				 timeout: Integer - the number of seconds before we abort the request.
	Output:		 None.
	Description: AJAX method. Sends a HTTP POST request with various pieces of form data. The aim is to
					(a) ascertain that the cottage is available, and (b) what the total price for the
					holiday is. The response is JSON encoded and consists of the following properties:
						errMsg: String - Contains the error message (if an error), else is empty.
						fieldIdfr: String - An identifier denoting which form field is in error. If
								there is no error then this is empty. This field may be omitted.
						price: Integer - The Price if one is calculated. This may be omitted or zero.
					Errors are handled by the same mechanism (show_results) as displays the successful
						output.
*/
HTTP.post = function(url, timeout) {
	var request = HTTP.newRequest();
	if (!(request)) { // We failed to obtain a request
		HTTP.showResult({ "errMsg" : "Sorry, your browser doesn't support this function" });
		return;
	}
	var timer;
	timer = setTimeout(function() {
			request.abort(); // Abort the request (note: this still triggers onreadystatechange)
			HTTP.showResult({ "errMsg" : "Request timed out, please re-try" });
			}, timeout * 1000);
	request.onreadystatechange = function() {
		if (request.readyState == 4) { // All data gathered
			if (timer)
				clearTimeout(timer);
			if (request.status == 200) // HTTP OK
				HTTP.showResult(json_parse(request.responseText));
			else if (request.status != 0) // Status = 0 occurs when we abort the request (don't show error)
				HTTP.showResult({ "errMsg" : "Request failed, please re-try" });
		}
	}
	// Clear existing error messages
	var formErrMsg = document.getElementById('formErrMsg'); // This is the 'main' error message paragraph
	if (formErrMsg) // If this paragraph exists...
		formErrMsg.style.visibility = 'hidden'; // ...hide it
	for (var i = 1; i < 5; i++) { // Clear all 'error' classes from the Holiday Detail Labels
		obj = document.getElementById('label0' + i);
		if (obj)
			obj.className = "";
	}
	// Create parameter list to send to server
	var bookingForm = document.getElementById('bookingForm');
	var params = { // Parameters to send to the server
		"action" : "check",
		"holiday" : bookingForm.holiday.value,
		"cottage" : bookingForm.cottage.value,
		"day" : bookingForm.day.value,
		"month" : bookingForm.month.value,
		"year" : bookingForm.year.value,
		"nights" : bookingForm.nights.value
	};
    request.open("POST", url);
	request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    request.send(HTTP.encodeFormData(params)); // Send the request (after encoding the parameters)
	// Show a 'checking...' message to the User
	var responseText = document.getElementById('responseText');
	responseText.className = '';
	responseText.innerHTML = "<em>Checking&#8230;</em>";
};
