/**
 * BookingForm.js - Booking form functionality
 * 
 * @author  Webstores <info at webstores dot nl>
 *          Copyright (c) Webstores internet totaalbureau <http://www.webstores.nl/>
 * 
 * @param {Mixed} form The CSS selector or object reference of the form
 */
function BookingForm(form, options) {
	this.form = $(form);
	this.options = options;
	this.construct();
};

BookingForm.prototype = {
	/**
	 * @constructor
	 */
	construct: function() {
		if(this.form.length) {
			this.options = $.extend({
				extrasClass: 'extras',
				activeClass: 'active',
				selectedClass: 'selected',
				priceUrl: '/nl/reserveren/supplement.json'
			}, this.options || {});
			
			if(this.form.is('form')) {
				this.form.validate({
					highlight: function(el, errorClass, validClass) {
						var errorEl = null;
						
						switch(el.type) {
							case 'radio':
								errorEl = $(el).parents('ul.options');
								break;
							case 'checkbox':
								errorEl = $(el).parent();
								break;
							default:
								errorEl = $(el);
								break;
						}
						
						errorEl.removeClass(validClass).addClass(errorClass);
					},
					unhighlight: function(el, errorClass, validClass) {
						var errorEl = null;
						
						switch(el.type) {
							case 'radio':
								errorEl = $(el).parents('ul.options');
								break;
							case 'checkbox':
								errorEl = $(el).parent();
								break;
							default:
								errorEl = $(el);
								break;
						}
						
						errorEl.removeClass(errorClass).addClass(validClass);
					}
				});
			}
			
			switch(this.form.attr('name')) {
				case 'book-step-4':
					this.addEventListenersStepFour();
					this.createExtrasTogglers();
					break;
				case 'book-step-5':
					$('#login-row', this.form).not('.expanded').hide();
					this.addEventListenersStepFive();
					break;
				case 'book-step-6':
					this.addEventListenersStepSix();
					break;
				case 'book-step-7':
					$('input[name="PM"]', this.form).css({
						position: 'absolute',
						left: '-9999px'
					});
					$('form.payment-method button').hide();
					this.addEventListenersStepSeven();
					break;
			}
		}
	},
	
	/**
	 * Add event listeners for step 4
	 */
	addEventListenersStepFour:function() {
		var self = this;
		
		this.addFormElementsEventHandler();
		
		$('.extras td.date input[type="checkbox"]').click(function() {
			self.dateClickHandler(this);
		});
	},
	
	/**
	 * Add event listeners for step 5
	 */
	addEventListenersStepFive: function() {
		var self = this;
		
		$('input[name="data[hasAccount]"]', this.form).click(function() {
			self.showLogin(parseInt($(this).val(), 10));
		});
	},
	
	/**
	 * Add event listeners for step 6
	 */
	addEventListenersStepSix: function() {
		this.form.submit(function() {
			if(!$('#terms:checked').length) {
				alert(lang.acceptTerms);
			}
		});
	},
	
	/**
	 * Add event listeners for step 7
	 */
	addEventListenersStepSeven: function() {
		$('.payment-method label.more', this.form).click(function() {
			var el = this;
			
			setTimeout(function() {
				el.form.submit();
			}, 10);
		});
	},
	
	/**
	 * Creates a toggler and radio togglers for the extras options (step 4)
	 */
	createExtrasTogglers: function() {
		var self = this;
		
		var extrasToggler = new Toggler($('.accordion', this.form), {
			togglerClass: 'extras-toggler',
			onAfterExpand: function(item) {
				$(item).prev('tr').addClass(self.options.activeClass);
			},
			onAfterCollapse: function(item) {
				$(item).prev('tr').removeClass(self.options.activeClass);
			}
		});
		
		$('table.overview .option input[type="radio"]').click(function() {
			var parentRow = $(this).parents('tr');
			var nextRow = parentRow.next('tr');
			
			if(parseInt($(this).val(), 10)) {
				if(nextRow.hasClass(self.options.extrasClass)) {
					extrasToggler.expand(nextRow);
				}
				self.selectExtrasRow(parentRow);
			}
			else {
				if(nextRow.hasClass(self.options.extrasClass)) {
					extrasToggler.collapse(nextRow);
				}
				self.deselectExtrasRow(parentRow);
			}
		});
	},
	
	/**
	 * Selects an extras row (step 4)
	 * 
	 * @param {Object} row The HTMLTableRowElement
	 */
	selectExtrasRow: function(row) {
		$(row).addClass(this.options.selectedClass);
	},
	
	/**
	 * Deselects an extras row (step 4)
	 * 
	 * @param {Object} row The HTMLTableRowElement
	 */
	deselectExtrasRow: function(row) {
		$(row).removeClass(this.options.selectedClass);
	},
	
	/**
	 * When a date checkbox fires onclick
	 * 
	 * @param {Object} el The HTMLInputElement
	 */
	dateClickHandler: function(el) {
		var prevRow;
		var checkbox = $(el);
		
		if(checkbox.attr('checked')) {
			prevRow = checkbox.parents('.extras').prev('tr');
			$('td.option:first input[type="radio"]', prevRow).click();
		}
	},
	
	/**
	 * Show or hide the login row (step 5)
	 * 
	 * @param {Boolean} show Show the login row (true) or hide it (false)
	 */
	showLogin: function(show) {
		var loginRow = $('#login-row', this.form);
		var toolbarControls = $('#booking-form-toolbar > ul', this.form);
		
		if(show) {
			loginRow.show();
			toolbarControls.hide();
			$('#login-email', this.form).focus();
		}
		else {
			loginRow.hide();
			toolbarControls.show();
		}
	},
	
	/**
	 * Adds an event handler to all form elements
	 * 
	 * @param {Function} handler The handler to call when the event type fires
	 */
	addFormElementsEventHandler: function(handler) {
		var eventType;
		var self = this;
		
		$(':input', this.form).each(function() {
			var eventType = '';
			
			if(this.name) {
				switch(this.nodeName) {
					case 'INPUT':
						switch(this.type) {
							case 'text':
								eventType = 'keyup';
								break;
							case 'radio':
							case 'checkbox':
								eventType = 'click';
								break;
						}
						break;
					case 'TEXTAREA':
						eventType = 'keyup';
						break;
					case 'SELECT':
						eventType = 'change';
						break;
				}
			}
			
			if(eventType) {
				$(this).bind(eventType, function() {
					self.sendRequest();
				});
			}
		});
	},
	
	/**
	 * Sends an HTTP request to get updated totals
	 */
	sendRequest: function() {
		var self = this;
		
		$.ajax({
			url: self.options.priceUrl,
			cache: false,
			dataType: 'json',
			type: 'POST',
			data: self.form.serialize(),
			success: function(data) {
				self.updatePrices(data);
			}
		});
	},
	
	/**
	 * Update booking prices
	 * 
	 * JSON:
	 * - type:  Prefix of a specific total ID, e.g.:
	 *          "extras" makes #extras-total, whereas
	 *          "grand" would make #grand-total
	 * - total: The total as string, with Euro sign
	 *          as HTML entity
	 * 
	 * @param {Object} data The JSON response
	 */
	updatePrices: function(data) {
		/*
		 * JSON
		 * 
			{
				"totals": [
					{
						"type": "extras",
						"total": "&euro; 49,00"
					},
					{
						"type": "grand",
						"total": "&euro; 311,50"
					}
				]
			}
		 */
		
		for(var i = 0; i < data.totals.length; i++) {
			$('#' + data.totals[i].type + '-total .label').html(data.totals[i].total);
		}
	}
};

