/**
 * Booking form JavaScript for DUT.
 *
 * @requires jQuery >= 1.2.6
 * @requires jQuery.validate >= 1.3
 * @authod James Hurst <james@riverratrecords.com>
 */
jQuery(document).ready(function() {
	
	DUT_Booking_Form = {
		// Properties
		form: jQuery('#dut-booking-form'),
		sections: jQuery('.dut-booking-form-section'),
		currentSection: 0,
	
		// Navigation buttons.
		nextButton: jQuery('<input type="button" name="next_button" id="next_button" value="Continue" />'),
		prevButton: jQuery('<input type="button" name="prev_button" id="prev_button" value="Go Back" />'),
	
	
		/**
		 * Initialises the form.
		 *
		 * This hides all of the sections, creates the navigation buttons, and then shows the first section.
		 */
		initialiseForm: function() {
			var self = this; // Keep a reference to this for enclosed function bodies.
			this.sections.hide(); // Hide everything.
			
			this.setFormValidation(); // Set Validation for the form
		
			// Bind the button events.
			this.nextButton.bind('click', function (e) { self.nextSection(e) });
			this.prevButton.bind('click', function (e) { self.previousSection(e) });
			this.nextButton.bind('click', function (e) { self.passengerNames(e) });
		
			// TODO: These should probably be appended somewhere nice in the form for display, rather than just at the end.
			this.form.append(this.prevButton);
			this.form.append(this.nextButton);
		
			// Show the first page.
			this.showSection(this.currentSection);
		},
	
		/**
		 * shows passenger names in room allocation dropdown
		 */
		passengerNames: function(e) {
			if ((this.currentSection + 1) == this.sections.length) {
				var id = 'room-allocation';
				if (document.getElementById(id)) {
					var fieldset = document.getElementById(id);
					var selects = fieldset.getElementsByTagName('select');
					var opts;
					for (var i=0,l=selects.length;i<l;i++) {
						opts = selects[i].getElementsByTagName('option');
						var text, fname, lname, name;
						for (var j=0,m=opts.length;j<m;j++) {
							fname = false;
							lname = false;
							text = opts[j].firstChild;
							if (j == 0) {
								fname = document.getElementById('lead-first-name').value;
								lname = document.getElementById('lead-surname').value;
							} else {
								fname = document.getElementById('p'+(j+1)+'-first-name').value;
								lname = document.getElementById('p'+(j+1)+'-surname').value;
							}
							if (fname && lname) {
								name = document.createTextNode(fname+' '+lname);
								opts[j].replaceChild(name,opts[j].firstChild);
							}
						}
					}
				}
			}
		},
	
		/**
		 * Navigates to the next section, only if the section validates.
		 */
		nextSection: function(e) {
			if (this.form.valid()) {
				if ((this.currentSection + 1) < this.sections.length) {
					this.removeValidationRules(this.currentSection);
					this.showSection(this.currentSection + 1);
					window.scrollTo(0, 0);
				}
			}
		},
	
	
		/**
		 * Navigates to the previous section.
		 */
		previousSection: function(e) {
			if (this.currentSection - 1 >= 0) {
				this.removeValidationRules(this.currentSection);
				this.showSection(this.currentSection - 1);
				window.scrollTo(0, 0);
			}
		},
	
	
		/**
		 * Shows the required section, hiding the currently shown section and enabling any validation rules.
		 */
		showSection: function(i) {
			if (this.currentSection != i) {
				this.sections.eq(this.currentSection).hide();
				this.currentSection = i;
			}
			this.setValidationRules();
			this.sections.eq(this.currentSection).show();
		
			this.showButtons();
		},

		/**
		 * Sets the form validation.
		 */		
		setFormValidation: function() {
		
			var self = this; // Keep a reference to this for enclosed function bodies.
		
			jQuery.validator.addMethod("date_dd_mm_yyyy", function(value, element) { // Add a new validation method - check if the date is correct and in format dd/mm/yyyy  
				return self.date_dd_mm_yyyy(value);
			}, "Please specify the correct date (dd/mm/yyyy)");
			
			
			jQuery.validator.addMethod("postcode_checker", function(value, element) { // Add a new validation method - check if the post code is correct 	
			 	return self.postcode_checker(value);
			}, "Please specify the correct postcode");
			
			jQuery.validator.addMethod("notEqual", function(value, element) { // Add a new validation method - check if values are not repeated	
				return self.notEqual(element);
			}, "Please select all passengers");
			
			this.form.validate(); // Setup validation. Rules are added as each section is shown.	
			
		},
	
		/**
		 * Sets the validation rules for the given screen.
		 */
		setValidationRules: function() {
											
			switch (this.currentSection) {
			case 0:
				// Lead title other only required if 'Other' is picked.
				jQuery('#lead-title-other').rules('add', { 
					required: function(element) { 
						return jQuery('#lead-title').val() == 'Other';
					}
				});
				jQuery('#lead-first-name').rules('add', { required: true });
				jQuery('#lead-surname').rules('add', { required: true });
				jQuery('#lead-home-phone').rules('add', { required: true });
				jQuery('#lead-email').rules('add', { required: true, email: true });
				jQuery('#lead-email-confirm').rules('add', { required: true, equalTo: "#lead-email" });
				jQuery('#lead-postcode').rules('add', { required: true, postcode_checker: true });
				jQuery('#lead-address-1').rules('add', { required: true });
				jQuery('#lead-city').rules('add', { required: true });
				jQuery('#lead-dob').rules('add', { date_dd_mm_yyyy: true });
				break;	
			case this.sections.length-1:
				jQuery('#room-allocation select:first').rules("add", { notEqual: true });
				jQuery('input[name="coachsection"]').each(function() {
					jQuery(this).rules("add", { required: true });
				});
				break;
			default:
				var p_id = "p"+(this.currentSection+1);
				jQuery('#'+p_id+'-title-other').rules('add', { 
					required: function(element) { 
						return jQuery('#'+p_id+'-title').val() == 'Other';
					}
				});
				jQuery('#'+p_id+'-first-name').rules('add', { required: true });
				jQuery('#'+p_id+'-surname').rules('add', { required: true });
				jQuery('#'+p_id+'-postcode').rules('add', { required: true, postcode_checker: true });
				jQuery('#'+p_id+'-address-1').rules('add', { required: true });
				jQuery('#'+p_id+'-city').rules('add', { required: true });
				jQuery('#'+p_id+'-dob').rules('add', { date_dd_mm_yyyy: true });
				break;
			}
			
		},

		/**
		 * Remove the validation rules for the given screen.
		 */
		removeValidationRules: function(section) {
			
			if (this.form.valid()) {
				return;
			}
			
			switch (section) {
			case 0:
				// Lead title other only required if 'Other' is picked.
				jQuery('#lead-title-other').removeClass("error").rules('remove');
				jQuery('#lead-first-name').removeClass("error").rules('remove');
				jQuery('#lead-surname').removeClass("error").rules('remove');
				jQuery('#lead-home-phone').removeClass("error").rules('remove');
				jQuery('#lead-email').removeClass("error").rules('remove');
				jQuery('#lead-email-confirm').removeClass("error").rules('remove');
				jQuery('#lead-postcode').removeClass("error").rules('remove');
				jQuery('#lead-removeress-1').removeClass("error").rules('remove');
				jQuery('#lead-city').removeClass("error").rules('remove');
				jQuery('#lead-dob').removeClass("error").rules('remove');
				break;	
			case this.sections.length-1:
				console.log("usuwam na koncu " + this.sections.length-1)
				jQuery('#room-allocation select:first').removeClass("error").rules("remove");
				jQuery('#room-allocation select').removeClass("error");
				jQuery('input[name="coachsection"]').each(function() {
					jQuery(this).removeClass("error").rules("remove");
				});
				break;
			default:
				var p_id = "p"+(section+1);
				jQuery('#'+p_id+'-title-other').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-first-name').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-surname').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-postcode').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-address-1').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-city').removeClass("error").rules('remove');
				jQuery('#'+p_id+'-dob').removeClass("error").rules('remove');
				break;
			}
					
		},	
	
		/**
		 * Shows and hides the navigation buttons depending on whether there are 
		 * more pages to navigate to.
		 */
		showButtons: function() {
			if ((this.currentSection + 1) < this.sections.length) {
				this.nextButton.show();
			} else {
				this.nextButton.hide();
			}
		
			if ((this.currentSection - 1) >= 0) {
				this.prevButton.show();
			} else {
				this.prevButton.hide();
			}
		},
		
		/**
		 * Validation Rules
		 * ================
		 */
		
		date_dd_mm_yyyy: function(value) {
			// DOB is not required
			if (value == "") {
				return true;
			}
			// Get separate date values from the input
			var day = value.split('/')[0];
		    var month = value.split('/')[1];
			var year = value.split('/')[2];

			// Create a new date using those values
			var date = new Date(year+"/"+month+"/"+day);

			if (date.toString() == "Invalid Date")
				return false;

			// Check if the new date matches the day and month and if the length of them is 2 
			var is_day = date.getDate() == day && day.length == 2 && !isNaN(day);
			var is_month = date.getMonth() == parseInt(parseFloat(month)) - 1 && month.length == 2 && !isNaN(month);

			// Check if year length is 4
			var is_year = year.length == 4 && !isNaN(year);

			// Return whenever the date is in format dd/mm/yyyy
			return is_day && is_month && is_year;
		},
		
		postcode_checker: function(toCheck) {
			// Permitted letters depend upon their position in the postcode.
			var alpha1 = "[abcdefghijklmnoprstuwyz]"; // Character 1
			var alpha2 = "[abcdefghklmnopqrstuvwxy]"; // Character 2
			var alpha3 = "[abcdefghjkstuw]"; // Character 3
			var alpha4 = "[abehmnprvwxy]"; // Character 4
			var alpha5 = "[abdefghjlnpqrstuwxyz]"; // Character 5

			// Array holds the regular expressions for the valid postcodes
			var pcexp = new Array ();

			// Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA
			pcexp.push (new RegExp ("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1,2})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));

			// Expression for postcodes: ANA NAA
			pcexp.push (new RegExp ("^(" + alpha1 + "{1}[0-9]{1}" + alpha3 + "{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));

			// Expression for postcodes: AANA NAA
			pcexp.push (new RegExp ("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1}" + alpha4 +"{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));

			// Exception for the special postcode GIR 0AA
			pcexp.push (/^(GIR)(\s*)(0AA)$/i);

			// Standard BFPO numbers
			pcexp.push (/^(bfpo)(\s*)([0-9]{1,4})$/i);

			// c/o BFPO numbers
			pcexp.push (/^(bfpo)(\s*)(c\/o\s*[0-9]{1,3})$/i);

			// Overseas Territories
			pcexp.push (/^([A-Z]{4})(\s*)(1ZZ)$/i);

			// Load up the string to check
			var postCode = toCheck;

			// Assume we're not going to find a valid postcode
			var valid = false;

			// Check the string against the types of post codes
			for ( var i=0; i<pcexp.length; i++) {
			 if (pcexp[i].test(postCode)) {

			// The post code is valid - split the post code into component parts
			pcexp[i].exec(postCode);

			// Copy it back into the original string, converting it to uppercase and
			// inserting a space between the inward and outward codes
			postCode = RegExp.$1.toUpperCase() + " " + RegExp.$3.toUpperCase();

			// If it is a BFPO c/o type postcode, tidy up the "c/o" part
			postCode = postCode.replace (/C\/O\s*/,"c/o ");

			// Load new postcode back into the form element
			valid = true;

			// Remember that we have found that the code is valid and break from loop
			break;
			}
			}

			// Return with either the reformatted valid postcode or the original invalid
			// postcode
			if (valid) {return postCode;} else return false;
		},
		
		notEqual: function(element) {
			var elements = jQuery(element.nodeName+"[name='"+element.name+"']");
			var validate = true;
			for (i=0; i<elements.length-1; i++) {
				for (j=i+1; j<elements.length; j++) {
					if (jQuery(elements[i]).val() == jQuery(elements[j]).val()) {
						jQuery(elements).addClass("error");
						return false;
					}
				}
			}
			jQuery(elements).removeClass("error");
			return true;
		}
	
	};

});
