/**
 *	Application Class
 *	-------------------------
 *	Site applications inherit from this class, change only with great care.
 *	Inherit with: NewApplicationClass = Class.extend(Application, [stuff]);
 */

function Application() {
	this.content = document.getElementById("content");
	this.linkRelations = [];
	this.inputRelations = [];
	
	EventListener.addEvent(document, 'click', this.handleClicks, this);
	EventListener.addEvent(window, 'unload', this.exit, this);
	
	this.registerLinkRelation(/display-/i, this.scope(this.handleDisplayLink));
	
	this.registerRememberRelations();
		
	if(window.DialogController) {
		if(!window.dialogController) {
			this.registerLinkRelation(/dialog-/i, this.scope(this.displayDialog));
			window.dialogController = new DialogController(this);
		}
		this.dialogs = window.dialogController;
	}

	if(window.Validator)
		this.validator = new Validator(this);
		
	// ajax error in includes/applications/applicationfeedback.shtml
	this.errorContent = document.getElementById('error-content');
	this.errorMessage = document.getElementById('error-message');
	
	// error-feedback & error-text are optional
	if(document.getElementById('error-feedback')) this.errorFeedback = document.getElementById('error-feedback');
	if(document.getElementById('error-text')) this.errorText = document.getElementById('error-text');

	// query print mode
	this.setPrintingMode();
	
	// replace form buttons
	FormButtons.replace();

	if(/en/i.test(getLanguage())) {
		Globals.MSG_REQUIRED  = Globals.MSG_REQUIRED_EN;
		Globals.MSG_ILLEGAL   =	Globals.MSG_ILLEGAL_EN;
		Globals.MSG_DEPENDENT =	Globals.MSG_DEPENDENT_EN;
		Globals.MSG_LOADING	  = Globals.MSG_LOADING_EN;
	}

	window.runningApplication = true;
}

Application.prototype = {
	// link and input relations
	registerLinkRelation:function(rel, handler) {
		this.linkRelations[this.linkRelations.length] = {type:rel, handler:handler};
	},

	registerInputRelation:function(rel, handler) {
		this.inputRelations[this.inputRelations.length] = {type:rel, handler:handler};
	},

	handleClicks:function(e) {
		var handler, rel;
		var target = EventListener.getTarget(e, 'a');
		var disabled = this.getDisabledState(target);
		
		if(!disabled) {
			if(target) {
				rel = target.getAttribute('rel');
				handler = this.searchHandler(rel, this.linkRelations);	
			} else {
				target = EventListener.getTarget(e, 'input');
				if(target) {
					rel = target.getAttribute('id');
					handler = this.searchHandler(rel, this.inputRelations);
				} 
			}
		}
		
		if(disabled || (handler && handler(target, rel))) {
			EventListener.preventDefault(e);
		}
	},
		getDisabledState:function(node) {
			var disabled = /(^|\s)disabled(\s|$)/;
			while(node) {
				if(disabled.test(node.className)) return true;
				node = node.parentNode;
			}

			return false;
		},

		searchHandler:function(rel, collection) {
			for (var relation,i=0; i<collection.length; i++) {
				relation = collection[i];
				if(relation.type.test(rel)) {
					return relation.handler;
				}
			}
		},
	
	validateOnSubmit:function(form, serverValidate) {
		EventListener.addEvent(form, 'submit', 
			function(e){
				this.validator.submit(form, serverValidate);
				EventListener.preventDefault(e);
			},
			this
		);
	},

	getProperty:function(name, form) {
		return (form && form[name])? 
			(form[name].value || Globals[name]) : Globals[name];
	},

	displayDialog:function(link, rel) {
		this.dialogs.displayDialog(link, rel);
		return true;
	},

	handleDisplayLink:function(link, displayRel) {
		var contain = getParentByTagName(link, 'div');
		ClassName.toggle(contain, displayRel);
		ClassName.toggle(link, 'active');
		
		try {
			if(/Toon\s/.test(link.innerHTML)) {
				link.innerHTML = link.innerHTML.replace(/Toon/, 'Verberg');
			} else if(/Verberg\s/.test(link.innerHTML)) {
				link.innerHTML = link.innerHTML.replace(/Verberg/, 'Toon');
			} else if(/Show\s/.test(link.innerHTML)) {
				link.innerHTML = link.innerHTML.replace(/Show/, 'Hide');
			} else if(/Hide\s/.test(link.innerHTML)) {
				link.innerHTML = link.innerHTML.replace(/Hide/, 'Show');
			}	
		} catch (e) {}

		return true;
	},

	loadValueFromCookie:function(elemId) {
		var elem = document.getElementById(elemId);
		var cookie = new Cookie(elem.id);
		if(cookie.get() && (!elem.value || elem.value == elem.title)){
			elem.value = unescape(cookie.get());
			var elemCheckbox = document.getElementById("remember-"+elemId);
			if (elemCheckbox) elemCheckbox.checked = 'checked';
		}
	},
	
	setCookieFromCheckbox:function(input, id) {
		// search for remember-
		var inputId = id.substring(id.indexOf("-")+1);
		var inputElem = document.getElementById(inputId);
		if(input.checked) {
			// set cookie
			if(inputElem.value.length > 0){
				var cookie = new Cookie(inputElem.id, inputElem.value, 14);
				cookie.set();
			}
		} else {
			// clear cookie
			var cookie = new Cookie(inputElem.id, '', -1);
			cookie.set();
		}	
		return false;
	},
	
	setCookieFromInputchange:function(e) {
		// search for remember-
		var inputElem = EventListener.getTarget(e, "input");
		var inputId = inputElem.id;
		var rememberCheckbox = document.getElementById("remember-"+inputId);
		if(rememberCheckbox.checked) {
			// set cookie
			if(inputElem.value.length > 0){
				var cookie = new Cookie(inputElem.id, inputElem.value, 14);
				cookie.set();
			}
		} else {
			// clear cookie
			//var cookie = new Cookie(inputElem.id, '', -1);
			//cookie.set();
		}	
		return false;
	},
	
	registerRememberRelations:function() {
		// handle checkboxes
		this.registerInputRelation(/remember-/i, this.scope(this.setCookieFromCheckbox));
		// handle inputboxes that are linked to tehe checkboxes
		var inputBoxes = document.getElementsByTagName("input",this.content);
		for (var i=0; i < inputBoxes.length; i++) {
			// look for remember checkboxes
			if (inputBoxes[i].id.indexOf("remember-") > -1) {
				var rememberCheckboxId = inputBoxes[i].id
				var inputId = rememberCheckboxId.substring(rememberCheckboxId.indexOf("-")+1);
				var inputElem = document.getElementById(inputId);
				EventListener.addEvent(inputElem, 'blur', this.scope(this.setCookieFromInputchange));
			}
		}
	},
	
	checkForError:function(xml){
		if (xml.getElementsByTagName("error").length > 0) {
			var error = xml.getElementsByTagName("error")[0];
			// check for fatal error
			var redirectElem = error.getElementsByTagName("redirect");
			if (redirectElem.length > 0) location.href = redirectElem[0].firstChild.nodeValue;
			else this.handleError(error);
			return true;
		}
		ClassName.remove(this.errorContent, "server-error");
		return false;
	},
	
	handleError:function(xml){
		this.errorMessage.innerHTML = xml.getElementsByTagName("message")[0].firstChild.nodeValue;
		
		var feedback = xml.getElementsByTagName("feedback")[0];
		if(feedback && feedback.firstChild) this.errorFeedback.innerHTML = feedback.firstChild.nodeValue;
		
		var extraInfo = xml.getElementsByTagName("text")[0];
		if(extraInfo && extraInfo.firstChild) {
			this.errorText.innerHTML = extraInfo.firstChild.nodeValue;
			ClassName.remove(this.errorContent, 'hide-extrainfo');
		} else {
			ClassName.add(this.errorContent, 'hide-extrainfo');
		}
		
		// show error content
		ClassName.add(this.errorContent, "server-error");

		// handle errorfields
		var fieldsElem = xml.getElementsByTagName("fields");
		if (fieldsElem.length > 0) {
			var fields = fieldsElem[0].getElementsByTagName("field");
			for (var i=0; i<fields.length; i++) {
				var inputId = fields[i].firstChild.nodeValue;
				var input = document.getElementById(inputId);
				if (input) ClassName.add(input.parentNode, 'error');
			}
		}
	},

	displayError:function(input, toggle) {
		var form = input.form;
		var error = this.getErrorElement(form);
		var origin = input.parentNode;
		if(/station/i.test(origin.className)) {
			origin = origin.parentNode;
		}
		ClassName[toggle? 'add':'remove'](origin, 'error');
		if(toggle) {
			error.style.display = 'block';
			error.innerHTML = Globals.MSG_REQUIRED;
		}
	},

	displayErrorMessage:function(form, message) {
		var error = this.getErrorElement(form);
		if(message) {
			error.innerHTML = Globals.MSG_ILLEGAL + message;
		} else {
			error.style.display = 'none';
		}
	},

	getErrorElement:function(form) {
		var nodes = form.getElementsByTagName("p");
		var errorReg = /(^|\s)error(\s|$)/i;
		for(var i=0; i<nodes.length; i++) {
			if(errorReg.test(nodes[i].className)) return nodes[i];
		}	return nodes[0];
	},

	displaySubject:function(select, subject) {
		var field = getParentByTagName(select, 'fieldset');
		if(subject) {
			ClassName.add(field, 'subject');
			var spans = field.getElementsByTagName("span"), subReg = /subject/i;
			for(var node,i=0; node = spans[i++];) {
				if(subReg.test(node.parentNode.className)) {
					node.innerHTML = subject;
					break;
				}
			}
		} else {
			ClassName.remove(field, 'subject');
		}
	},

	getFormValues:function(form) {
		var element, type, post = '';
		var input = /(text|select)/i;
		var hidden = /hidden/i;
		var select = /select/i;
		var elements = form.elements || form.dynamicElements;
		for (var i=0; i<elements.length; i++) {
			element = elements[i];
			type = element.type;
			if((input.test(type) && element.offsetHeight) || hidden.test(type) || element.checked) {
				if(select.test(element.nodeName)) {
					var opt = element[element.selectedIndex];
					post += element.name + '=' + escape(opt.value || opt.text) + '&';
				} else {
					post += element.name + '=' + escape(element.value) + '&';
				}
			}
		}
		return post;
	},

	parseXMLNode:function(node) {
		var collection = {};
		for (var child,i=0; i<node.childNodes.length; i++) {
			child = node.childNodes[i];
			if(child.nodeType == 1) {
				collection[child.nodeName.toLowerCase()] = child.firstChild.nodeValue;
			}
		}
		return collection;
	},

	parseToHTML:function(htmlString, rootNode) {
		var buffer = document.createElement('div');
		buffer.innerHTML = htmlString;
		return buffer.getElementsByTagName(rootNode)[0];
	},

	setPrintingMode:function() {
		var dialog = document.getElementById("togo-printmenu");
		var form = dialog? dialog.getElementsByTagName("form")[0] : null;
		if(form) {
			// add hidden input to tell togo script to print spi-style
			// IE won't do createElement('input');
			var spi = document.createElement('span');
			spi.innerHTML = '<input type="hidden" name="spi" value="true" />';
			form.appendChild(spi);
		}
	},

	exit:function() {
		var events = EventListener.getEvents(); // all of them
		EventListener.removeEvents(events);
		this.linkRelations = null;
		this.inputRelations = null;
	},
	
	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}

/**
 *	Inheritance
 *	--------------------------
 */

Class = {
	extend:function(Base, constructor, prototype) {
		var Extended = function() {
			Base.apply(this, arguments);
			constructor.apply(this, arguments);
		}

		this.implement(Extended, Base.prototype);
		if(prototype) this.implement(Extended, prototype);
		return Extended;
	},

	implement:function(Class, protoface) {
		for(var i in protoface) {
			Class.prototype[i] = protoface[i];
		}
	}
}

/**
 *	TravelApplication 
 *	- extends Application
 *	-------------------------
 *	Travel based applications inherit from this class, change only with great care.
 */

TravelApplication = Class.extend(
	// base class
	Application, 
	
	// constructor
	function(){
		this.registerInputRelation(/-viastation/i, this.scope(this.toggleInputStatus));
		
		if(window.AutoComplete) {
			this.autoComplete = new AutoComplete(this);
			this.autoComplete.setMode('station', 'buffer');
			this.autoComplete.setMode('STATION', 'buffer');
			this.autoComplete.setMode('plaatsnaam', 'change');
			this.autoComplete.setMode('CITY', 'change');
		}
	},{	
		
	// prototype	
	initializeForm:function(form) {
		var select, selects = form.getElementsByTagName("select");
		var ov9292 = /9292/;
		for (var i=0; i<selects.length; i++) {
			select = selects[i];
			if(ClassName.contains(select, 'location-type')) {
				EventListener.addEvent(select, 'change', this.getLocationType, this);
			} else if(ov9292.test(select.options[select.selectedIndex].text)){
				this.handle9292OV({ target: select });
			}
		}
		
		this.addAutocomplete(form);

		if(/page-home/i.test(document.body.className)) {
			var now = new Date();
			var dates = getElementsByAttributeValue('class', 'date', form);
			for(var i=0; i<dates.length; i++) {
				this.setCurrentDate(dates[i], now);
			}

			var times = getElementsByAttributeValue('class', 'time', form);
			for(var i=0; i<times.length; i++) {
				this.setCurrentTime(times[i], now);
			}
		}
	},
		setCurrentDate:function(section, date) {
			try {
				var inputs = section.getElementsByTagName("input");
				var pad = /[0-9]{2}$/, i = Math.min(inputs.length, 4);
				inputs[i-3].value = pad.exec('0'+date.getDate());
				inputs[i-2].value = pad.exec('0'+(date.getMonth() +1));
				inputs[i-1].value = date.getFullYear();
			} catch (e) {}
		},

		setCurrentTime:function(section, date) {
			try {
				var inputs = section.getElementsByTagName("input");
				var pad = /[0-9]{2}$/;
				inputs[0].value = pad.exec('0'+date.getHours());
				inputs[1].value = pad.exec('0'+date.getMinutes());
			} catch (e) {}
		},

	addAutocomplete:function(form) {
		if(this.autoComplete)
			this.autoComplete.addElements(form);
	},

	getLocationType:function(e) {
		var select = EventListener.getTarget(e, 'select');
			var type = select[select.selectedIndex].value;
		this.handleLocationType(type, select);
	},

	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);

		try {
			var fragmentForm = document.getElementById("location-fragments");
			var fragmentHtml = fragmentForm.elements['location-'+locationType].value;
			var transportHTML = fragmentForm.elements[type].value;

			fragmentHtml = fragmentHtml.replace(/\[\$\]/mg, prefix);
			transportHTML = transportHTML.replace(/\[\$\]/mg, prefix);
		} catch (e) {}

			this.displayError(select, false);
			var transport, node = this.parseToHTML(fragmentHtml, 'fieldset');

			if(select.selectedIndex > 0 && (!showType || (showType != 'false'))) {
				transport = this.parseToHTML(transportHTML, 'div');
				node.appendChild(transport);
			}

			if(current) {
				section.replaceChild(node, current);
			} else {
				section.appendChild(node)
			}

			var selects = node.getElementsByTagName("select");
			this.autoComplete.addElements(node);
			if(selects.length > 0) {
				var method = selects[selects.length-1];
				this.autoComplete.addDynamicSelect(method, node);
				EventListener.addEvent(method, 'change', this.handle9292OV, this);
			}
	},

	handle9292OV:function(e) {
		// entire heen- or terugreis must use 9292ov; different service.
		var origin = EventListener.getTarget(e, 'select');
		var field = getParentByTagName(getParentByTagName(origin, 'fieldset'), 'fieldset');
		var methods = getElementsByAttributeValue('class', 'travel-options', field);

		var value = origin? origin[origin.selectedIndex].text : '';
		var is9292 = /9292ov/i;
		
		for(var select,val,i=0; i<methods.length; i++) {
			select = methods[i].getElementsByTagName("select")[0];
			val = select[select.selectedIndex].text;
						
			if(is9292.test(value) && select != origin) select.selectedIndex = select.options.length-1;
			if(is9292.test(val) && !is9292.test(value) && select != origin) select.selectedIndex = 0;
		}

		this.lastKnownOrigin = is9292.test(value)? origin : null;
	},

	requestMethod:function() {
		if(this.lastKnownOrigin)
			this.handle9292OV({ target:this.lastKnownOrigin });
	},

	displayDialog:function(link, rel) {
		this.dialogs.displayDialog(link, rel);
		if(this.autoComplete) {
			this.autoComplete.close();
		}
		return true;
	},

	toggleInputStatus:function(input, id) {
		// check for error labels (betalingsmethode)
		var methods = getElementsByAttributeValue('class', 'method', input.parentNode.parentNode);
		for (i = 0;i <methods.length; i++){
			ClassName.remove(methods[i], 'error');
		}
		if(input.checked) {
			if (input.type == "radio"){
				for (i = 0;i <this.form[input.name].length; i++){
					if(ClassName.contains(this.form[input.name][i].parentNode, 'selected')){
						ClassName.remove(this.form[input.name][i].parentNode, 'selected');				  
					};
				}	
			}
			ClassName.add(input.parentNode, 'selected');
		} else {
			ClassName.remove(input.parentNode, 'selected');
			ClassName.remove(input.parentNode, 'error');

			// remove text input value when hidden
			var text = getElementsByAttributeValue('class', 'text', input.parentNode);
			if(text[0]) text[0].value = '';
		}	
		return false;
	},

	exit:function() {
		Application.prototype.exit.call(this);
		if(this.autoComplete) {
			this.autoComplete.unload();
		}
	}
});

/**
 *	onDOMContentLoaded
 *	-------------------------
 */

var DOMContent = {
	init:function() {
		this.handlers = [];
		var onload = function() { DOMContent.onload(); }
		try { 
			window.addEventListener('load', onload, false);
			document.addEventListener('DOMContentLoaded', onload, false);
		} catch(e) {
			window.attachEvent('onload', onload);
			/*@cc_on @*/
			/*@if (@_win32)
				document.write('<script id="_ie_onload" defer src="javascript:void(0);"><\/script>');
				var script = document.getElementById('_ie_onload');
				script.onreadystatechange = function() {
					if(this.readyState == "complete") onload();
				};
			/*@end @*/
		}

		if(/webkit/i.test(navigator.userAgent)) {
			this.timer = setInterval(function() {
				if(/loaded|complete/.test(document.readyState)) onload();
			}, 10);
		}
	},

	onload:function() {
		clearInterval(this.timer);
		if(!document.getElementsByTagName("body")[0]) return; // should never happen
		for(var handler,i=0; i<this.handlers.length; i++) {
			try { 
				handler = this.handlers[i];
				if(!handler.executed) {
					handler.executed = true;
					handler();
				}
			} catch (e){
				handler.executed = false;
			}
		}
	},

	addListener:function(handler) {
		if(!this.handlers) this.init(); //jit
		this.handlers[this.handlers.length] = handler;
	}
}

/**
 *	Form buttons replacement
 *	--------------------------
 */

FormButtons = {
	SUBMIT:		/(submit|reset)/i,
	REPLACE:	/button(\s.*)?$/,
	REPLACED:	/replaced/,

	replace:function(root) {
		var inputs = (root || document).getElementsByTagName("input");
		for(var input, i=0; i<inputs.length; i++) {
			input = inputs[i];
			if(this.SUBMIT.test(input.type)) this.replaceInput(input);
		}
	},

	replaceInput:function(input) {
		if(!this.REPLACE.test(input.className) || this.REPLACED.test(input.className)) return;

		var type = this.REPLACE.exec(input.className)[0];
		var span = document.createElement('span');
		span.innerHTML = input.value;
		
		var link = document.createElement('a');
		link.setAttribute('href', '#');
		link.setAttribute('rel', input.name);
		link.className = type;			
		link.appendChild(span);

		var stat = input.getAttribute('ns:sitestat');
		if(stat) { 
			link.setAttribute('ns:sitestat', stat); 
		}

		input.parentNode.insertBefore(link, input);

		var css = input.style;
		css.position = 'absolute';
		css.left = '-3000px';
		css.display = 'block';
		css.width =  '0'

		ClassName.add(input, 'replaced');
	}
}	
