/**
 * NS Reisplanner application
 *
 * @version   1.00.090812
 * @author    LBI Lost Boys
 */
NS(function($){

	var REG_LOCATIONTYPE = /location-type/i;
	var REG_TRAVELOPTIONS = /travel-options/i;
	var REG_ALTERNATE = /alternative(?!(\s+station))/i;

	function Reisplanner() {
		this.form = $("#form-reisplanner");

		NS.subscribe('change', this.handleChange.bind(this));
	
		NS.relateLink(/poi-/, this.handlePOIClick.bind(this));
		
		NS.relateInput(/-planterugreis/i, this.toggleRoundtrip.bind(this));
		NS.relateInput(/-viastation/i, this.toggleViaStation.bind(this));

		// if remote call returned with an error while requesting advice, call client side validation
		var regRemote = /\/remote\.s?html/i;
		var regAdvice = /&advice(=|&|$)/i;
		var loc = window.location;
		
		if(regRemote.test(loc) && regAdvice.test(loc)) {
			var form = this.form[0];
			// must be delayed, or NS.findApplication won't return the reisplanner app; doesn't exist yet
			$(window).bind('load', function(){			
				NS.Dispatcher.fire('submit', form);
			});
		}
	}

	Reisplanner.prototype = {
		Defaults: {
			validateRequired: true,
			validateServer: true,
			replaceInputs: true,
			simulateClick: true
		},

		owns: function(form) {
			return this.form[0] == form;
		},

		prefers: function(setting) {
			return this.Defaults[setting];
		},

		handleChange:function(e) {
			var element = e.target;
			var field = $(element).closest('fieldset')[0];

			// update alternative location fragments
			if(REG_LOCATIONTYPE.test(element.className)) {
				var type = element[element.selectedIndex].value;
				this.handleLocationType(type, element);
				NS.log("handleChange: location type");
				return;
			}
			
			// check for 9292
			if(REG_TRAVELOPTIONS.test(element.parentNode.className)) {
				this.handleOV9292(element);
				NS.log("handleChange: handle 9292");
				return;
			}
		
			// update travel methods
			if(field && REG_ALTERNATE.test(field.className)) {
				this.handleTravelMethod(element, field);
				NS.log("handleChange: travel method");
				return;
			}
		},

		toggleViaStation:function(input){
			var action = input.checked? 'addClass' : 'removeClass';
			$(input.parentNode)[action]('selected');
		},

		/**
		 * Roundtrip functions
		 */
		toggleRoundtrip:function(input) {
			if(input.checked) {
				var post = NS.getFormValues(input.form);
				NS.XHR.sendAndLoad(post, NS.getProperty('POST_RETURNFORM'), this.handleRoundtrip.bind(this));
				this.form.addClass('roundtrip');
			} else {
				this.form.removeClass('roundtrip');
			}
		},

		handleRoundtrip:function(xml) {
			var html = $("form", xml).text();
			var section = $("#travel-return");
			NS.DOM.write(section, html);
		},

		/**
		 * Location type functions
		 */
		handleLocationType:function(locationType, select) {
			var prefix = select.getAttribute('ns:prefix');
			var section = select.parentNode;
			var showType = select.getAttribute('ns:showtransport');
			var current = section.getElementsByTagName("fieldset")[0];
			var type = '' + (/location-[a-z]+/).exec(section.className);
			
			var fHtml; 
			var tHtml; 
			var form;
			try {
				form = document.getElementById("location-fragments");
				fHtml = form.elements['location-'+locationType].value;
				tHtml = form.elements[type].value;

				fHtml = fHtml.replace(/\[\$\]/mg, prefix);
				tHtml = tHtml.replace(/\[\$\]/mg, prefix);
			} catch (e) {}

			var transport;
			var fragment = $(fHtml);
			if(select.selectedIndex > 0 && (!showType || (showType != 'false')) && !fragment.hasClass('findpoi')) {
				transport = $(tHtml);
				fragment.append(transport);
			}

			if(current) {
				NS.DOM.replace(fragment, current);
			} else {
				NS.DOM.append(section, fragment);
			}
						
			var remembered = this.form[0].rememberAddress;
			if(/address/i.test(locationType) && remembered && remembered.checked) {
				this.requestRememberedValues(locationType, select);
			}
		},
		
		/**
		 * remembered address values
		 */
		requestRememberedValues:function(type, select) {
			var post = select.name + '=' + encodeURIComponent(type),
				url = NS.getProperty('GET_REMEMBERED', this.form[0]);
			
			NS.XHR.sendAndLoad(post, url, this.displayRememberedValues.bind(this));
		},
		
		displayRememberedValues:function(xml) {
			var input, fields = $(xml).find('input');
			for(var i=0; i<fields.length; i++) {
				var name = fields[i].getAttribute('name');
				input = this.form[0].elements[name];
				if(input) {
					var value = fields[i].getAttribute('value');
					$(input).focus();
					input.value = value;
				}
			}

			if(input) {
				NS.Dispatcher.fire('change', input);
			}
		},

		findLanguage:function(field) {
			var form = $(field).closest('form');
			if(form.length) {
				var lang = form[0].elements['language'];
				return lang? lang.value : null;
			}
			return null;
		},

		/**
		 * Travel method functions
		 */
		handleTravelMethod:function(input, fieldset) {
			var method = $('select:last', fieldset);
			if(!method[0] || input == method[0]) {
				// update onchange other than method itself
				return;
			}
			var inputs = $('input:text, select:not(:last)', fieldset);
			var regText = /text/i; 
			var post = '';
			var url = Globals.POST_ALT_TRAVEL;
			
			var lang = this.findLanguage(fieldset);
			if(lang) {
				post += 'language=' + lang + '&';
			}

			for(var i=0; i<inputs.length; i++) {
				var element = inputs[i];
				if((regText.test(element.type) && element.value) || element.selectedIndex > 0) {
					post += element.name + '=' + encodeURIComponent(element.value) + '&';
				} else {
					return;
				}
			}
			NS.XHR.sendAndLoad(post, url, function(response){
				NS.autocomplete.handleResponse(response, method[0]);				
				var items = $(response).find('item');
				if(items.length === 0) {
					var error = $(response).find('error').text();
					NS.Interface.displayErrorMessage(error, input.form);
				} else {
					NS.Interface.displayErrorMessage(false, input.form);
					var subject = $(response).find('subject').text();
					this.displaySubject(subject, fieldset);
					this.pollOV9292();
				}				
			}.bind(this));
		},
		
		displaySubject:function(subject, fieldset) {
			var jFieldset = $(fieldset);
			if(subject) {
				jFieldset.addClass('subject');
				jFieldset.find('.subject span').html(subject);
			} else {
				jFieldset.removeClass('subject');
			}
		},

		/**
		 * OV9292 check; either all methods must select it, or none may.
		 */
		handleOV9292:function(select) {
			var value = select[select.selectedIndex].value,
				methods = $('div.travel-options select'),
				reg9292 = /OV9292/i,
				has9292 = false;
				
			for(var i=0; i<methods.length; i++) {
				var val = $(methods[i]).val();
				if(reg9292.test(val)) {
					has9292 = true;
					break;
				}
			}
			
			if(has9292) {
				if(/OV9292/i.test(value)) {
					// if 9292 was selected, all travel methods must select it
					methods.val(value);
				} else {
					// otherwise, none may select it.
					methods.not(select).val('');
				}
			}
		},

		pollOV9292:function() {
			var methods = $('div.travel-options select');
			for(var i=0; i<methods.length; i++) {
				var select = methods[i], value = select[select.selectedIndex].value;
				if(/OV9292/i.test(value)) {
					methods.val(value);
					return;
				}
			}
		},

		/**
		 * Find POI functions
		 */
		handlePOIClick:function(link, rel) {
			var type = /poi-([a-z]+)/i.exec(rel)[1];
			switch (type) {
				case 'search':
					var field = $(link).closest('fieldset')[0];
					var inputs = field.getElementsByTagName("input");
					var post = NS.getFormValues(field);
					
					var lang = this.findLanguage(field);
					if(lang) {
						post += 'language=' + lang + '&';
					}
					
					NS.XHR.sendAndLoad(post, NS.getProperty('POST_POI_SEARCH'), function(xml){
						var message = $(xml).find('error').text();
						if (message && /[a-z]/i.test(message)) {
							NS.Interface.displayError(inputs[0], true);
							NS.Interface.displayError(inputs[1], true);
							NS.Interface.displayErrorMessage(message, $(link).closest('form')[0]);
						} else {
							NS.DOM.write(field, $('response', xml).text());
						}
					});
				break;

				case 'reset':
					var select = $(link).closest('div').find('select')[0];
					var prefix = select.getAttribute('ns:prefix');
					var form = select.form;
					var what = form[prefix + 'what'].value;
					var where = form[prefix + 'where'].value;
					var type = select[select.selectedIndex].value;

					this.handleLocationType(type, select);
					
					//trigger a focus event before entering values
					form[prefix + 'where'].focus();
					form[prefix + 'where'].value = where;
					form[prefix + 'what'].focus();
					form[prefix + 'what'].value = what;
				break;
			}
			return true;
		}
	};

	/**
	 * Bind to NS.initialize
	 */
	NS.subscribe('initialize', function(){
		NS.addApplication('reisplanner', new Reisplanner());
	});
});