/**
 *	Reisplanner dialogcontroller
 *	--------------------------
 */

function DialogController(gui) {
	this.gui = gui;
	this.dialogTypes = {};
	this.dialogs = {};
	
	// iframe for covering up select boxes in IE
	if(/msie (5|6)/i.test(navigator.userAgent)) {
		this.ieFrame = document.createElement("iframe");
		this.ieFrame.className = "cover-frm";
		this.ieFrame.frameBorder = 0;
		document.getElementById("canvas").appendChild(this.ieFrame);
	}

	this.register('help', HelpDialog);
	this.register('facilities', StationsDialog);
	this.register('departures', StationsDialog);
	this.register('calendar', CalendarDialog);
	this.register('date', CalendarDialog);
	this.register('provinces', ProvincesDialog);
	this.register('emailmenu', SendFriendDialog);
	this.register('smsinfo', SMSDialog);

	EventListener.addEvent(document, 'click', this.scope(this.tryClose));
}

DialogController.prototype = {
	register:function(type, constructor) {
		this.dialogTypes[type] = constructor;
	},

	displayDialog:function(link, dialogRel) {
		if(this.currentDialog) {
			this.currentDialog.display(false);
			this.toggleIEFrame(false);
		}

		var type = /dialog-([a-z0-9]+)/i.exec(dialogRel)[1];
		switch (type) {
			case 'close': break;
			case 'confirm':
				window.location = this.currentDialog.origin.getAttribute('href');
			break;
			default:
				var element = document.getElementById(dialogRel);
				return this.createDialog(element, link, type);
			break;
		}

		this.currentDialog = null;
	},

	createDialog:function(element, link, type) {
		var dialog = this.dialogs[type];
		if(!dialog) {
			var DialogClass = this.dialogTypes[type] || Dialog;
			dialog = new DialogClass(element, this, this.gui, type);
		}
		
		this.currentDialog = this.dialogs[type] = dialog;
		dialog.setOrigin(link);
		dialog.toggle(true);
		return dialog;
	},

	tryClose:function(e) {
		if(this.currentDialog) {
			var node = EventListener.getTarget(e);
			this.currentDialog.tryClose(node);
		}
	},

	toggleIEFrame:function(toggle, dialog) {
		if(this.ieFrame){
			var frm = this.ieFrame.style;
			if(toggle) {
				frm.left = calculateLeft(dialog) + "px";
				frm.top = (calculateTop(dialog) - 6) + "px";
				frm.width = (dialog.offsetWidth - 5) + "px";
				frm.height = (dialog.offsetHeight + 8) + "px";
				frm.display = "block";
			} else {
				frm.display = "none";
			}
		}
	},

	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}

/**
 *	Dialog
 *	--------------------------
 */

function Dialog(element, controller, gui, type) {
	this.container = element;
	this.controller = controller;
	this.gui = gui;
	this.type = type;
}

Dialog.prototype = {
	setAction:function(action) { this.action = action; },
	setOrigin:function(origin) { this.origin = origin; },
	action:function() {},
	activate:function(){},

	toggle:function(toggle) {
		this.activate(toggle);
		this.display(toggle);
		this.controller.toggleIEFrame(toggle, this.container);
	},

	display:function(toggle) {
		var dialog = this.container;
		var origin = this.origin;

		var availHeight = window.innerHeight || document.documentElement.clientHeight;
		var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
		var pageBottom = availHeight + scrollTop;
		
		var css = dialog.style;
		css.display = toggle? 'block':'none';

		var x = calculateLeft(origin);
		var y = calculateTop(origin);
		var h = dialog.offsetHeight;
		
		
		ClassName.remove(dialog, 'east');
		ClassName.add(dialog, 'west');

		if(x < (dialog.offsetWidth + 30)) {
			ClassName.swap(dialog, 'west', 'east');
		}
		
		var ty = (y + 10 - h/2);
		if(ty < (scrollTop + 18)) ty = scrollTop + 18;
		if((ty + h) > pageBottom) ty = pageBottom - h -10;

		var arrow = getElementsByAttributeValue("class", "togo-arrow", dialog)[0];
		var ah = arrow.offsetHeight;
		var ay = (y - ty  +10);
		if(ay < 20) ay = 20;
		if((ay + ah/2) > h) ay = h - ah/2;
		arrow.style.top = ay + 'px';
		
		//if (this.container.parentNode.id === "vraag-en-antwoord") {x = x-718;ty = ty-65;}
		css.left = x + 'px';
		css.top = ty + 'px';
		
		dialog.style.visibility = toggle? 'visible':'hidden';
	},

	tryClose:function(node) {
		var auto = document.getElementById("autoComplete");
		while(node) {
			if(node == this.container || node == this.origin || (auto && node == auto)) return;
			node = node.parentNode;
		}	this.toggle(false);
	},

	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}

/**
 *	Help 
 *	--------------------------
 */

HelpDialog = Class.extend(
	Dialog,
	function(){
	}, {

	activate:function(){
		this.container.getElementsByTagName("p")[0].innerHTML = 
			this.origin.getAttribute('title');
	}
});

/**
 *	Facilities and Stops
 *	--------------------------
 */

StationsDialog = Class.extend(
	Dialog, 
	function(){
	}, {

	activate:function(toggle) {
		if(toggle)
			this.gui.getStops(this.origin, this.type, this.scope(this.parseStops));
	},

	parseStops:function(xml) {
		var stops = xml.getElementsByTagName("stop");
		var stop, result = [];
		for (var i=0; i<stops.length; i++) {
			result[result.length] = this.gui.parseXMLNode(stops[i]);
		}

		this.updateStops(result);
		this.display(true); // reposition after flow change
	},

	updateStops:function(stops) {
		var list = document.createElement('ul');
		list.className = 'dialog-list';
		var url = /facilities/i.test(this.type) ?
			Globals.URL_STATION_VOORZIENINGEN : Globals.URL_STATION_VERTREKTIJDEN;

		for(var link,item,i=0; i<stops.length; i++) {
			link = document.createElement('a');
			var separator = (/\?/i.test(url)? (/&$/.test(url)? '':'&'):'?');
			link.setAttribute('href', url + separator +'station=' + stops[i].naam);
			link.innerHTML = stops[i].naam;

			item = document.createElement('li');
			item.appendChild(link);
			list.appendChild(item);
		}	

		var insert = this.container.getElementsByTagName("form")[0];
		var existing = insert.parentNode.getElementsByTagName("ul")[0];
		if(existing) {
			insert.parentNode.replaceChild(list, existing);
		} else {
			insert.parentNode.insertBefore(list, insert);
		}
	}
});

/**
 *	Calendar 
 *	--------------------------
 */

CalendarDialog = Class.extend(
	Dialog, 
	function(){
		if(window.Calendar) {
			var settings = {};
			if(/dialog-date/.test(this.container.id)) {
				settings.allowPast = true;
			}
			this.calendar = new Calendar(this.container, settings);
			this.calendar.setAction(this.scope(this.updateCalendar));
		}
	}, {

	activate:function(toggle) {
		if(toggle) {
			var inputs = this.origin.parentNode.getElementsByTagName("input");
			var i = Math.min(inputs.length, 4);
			var date = new Date(
				parseInt(inputs[i-1].value, 10),
				parseInt(inputs[i-2].value, 10)-1, 
				parseInt(inputs[i-3].value, 10)
			);

			if(!date.getTime()) date = new Date();
			this.calendar.setDate(date);
		}
	},
	
	updateCalendar:function(date) {
		var inputs = this.origin.parentNode.getElementsByTagName("input");
		var i = Math.min(inputs.length, 4);
		inputs[i-3].value = date.getDate();
		inputs[i-2].value = date.getMonth() + 1; // month is zero based
		inputs[i-1].value = date.getFullYear();
		
		try {
			// for strange selection bug in firefox
			var call = this.scope(function() { this.display(false); });
			setTimeout(call, 100);	
		} catch (e) {
			this.display(false);
		}
	}
});

/**
 *	Provinces
 *	--------------------------
 */

ProvincesDialog = Class.extend(
	Dialog, 
	function(){
		var provinces = document.getElementById("searchProv");
		if(provinces) {
			EventListener.addEvent(provinces, 'mouseover', this.scope(this.handleProvince));
			EventListener.addEvent(provinces, 'click', this.scope(this.handleProvinceClick));
		}
	}, {

	activate:function(toggle) {
		if(!toggle) return
		try {
			var select = this.origin.parentNode.parentNode.getElementsByTagName("select")[0];
			var province = select[select.selectedIndex].text;
			this.setCurrentProvince(province.toLowerCase());
		} catch (e) {}
	},
	
	action:function(province) {
		this.gui.selectProvince(province);
	},

	handleProvince:function(e){
		var area = EventListener.getTarget(e, 'area');
		if(area) {
			var province = area.getAttribute('title').toLowerCase();
			this.setCurrentProvince(province);
		}
	},

	setCurrentProvince:function(province) {
		if(this.currentProvince) {
			ClassName.remove(this.container, this.currentProvince);
		}	ClassName.add(this.container, this.currentProvince = province);
	},

	handleProvinceClick:function(e){
		this.action(this.currentProvince);
		EventListener.cancelEvent(e);
		this.display(false);
	}
});

/**
 *	Send to friend
 *	--------------------------
 */

SendFriendDialog = Class.extend(
	Dialog, 
	function(){
	}, {

	handleSendToFriend:function(link) {
		var form = getParentByTagName(link, 'form');		
		var email = form.senderemail, recemail = form.receiveremail;	
		this.gui.displayError(email, false);
		this.gui.displayError(recemail, false);

		if(!email.value || !/^[^@]+@([^.]+\.)+[a-z]+$/.test(email.value))
			return this.gui.displayError(email, true);
		if(!form.toself.checked && !recemail.value || !/^[^@]+@([^.]+\.)+[a-z]+$/.test(recemail.value))
			return this.gui.displayError(recemail, true);
		
		var post = this.gui.getFormValues(form);
		var action = form.action;
		if(form.responsetype)
			form.responsetype.value = 'xml';

		XMLHttp.sendAndLoad(post, action, this.scope(this.finalizeSendToFriend));
	},
	
	finalizeSendToFriend:function(xml) {
		this.controller.displayDialog(this.origin, 'dialog-emailsentmenu');
		try {
			this.controller.currentDialog.container.getElementsByTagName("p")[0].innerHTML = 
				xml.getElementsByTagName('response')[0].firstChild.nodeValue;
		} catch (e) { }
	}
});

/**
 *	SMS Info
 *	--------------------------
 */

SMSDialog = Class.extend(
	Dialog,
	function() {
		this.gui.registerLinkRelation(/sms-[a-z]+/, this.scope(this.handleSMSClick));
		this.content = document.getElementById("sms-informatie");
	}, {

	activate:function(toggle) {
		if(toggle) {
			this.write('<p> &nbsp; </p>');
			this.getContent(Globals.GET_SMS_FORM);
		}
	},
	
	handleSMSClick:function(link, rel) {
		var type = /sms-([a-z]+)/i.exec(rel)[1];
		var form = getParentByTagName(link, 'form');
		var travelType = this.getTravelType(this.origin);
		var post = form? (this.gui.getSearchValues() + this.gui.getFormValues(form) + this.gui.advisor.getDetails(travelType)) : null;
		if(post) { this.lastPost = post; }

		switch (type) {
			case 'submit':		this.getContent(Globals.POST_SMS_DETAILS, post); break;
			case 'retry':		this.getContent(Globals.POST_SMS_DETAILS, this.lastPost); break;
			case 'subscribe':	
				if(this.validSubscription(form)) {
					this.getContent(Globals.POST_SMS_SUBSCRIBE, post); 
				} else {
					return true;
				}
			break;
			case 'example':		this.getContent(Globals.GET_SMS_EXAMPLE); break;
			case 'info':		this.getContent(Globals.GET_SMS_INFO); break;
			case 'detailinfo':	this.getContent(Globals.GET_SMS_DETAILINFO); break;
			case 'reset':		this.getContent(Globals.GET_SMS_FORM); break;
		}

		if(ClassName.contains(link, 'button')) {
			ClassName.add(link.parentNode, 'disabled');
		}

		return true;
	},

	validSubscription:function(form) {
		var checkedOne = false, checkReg = /checkbox/i;
		for(var i=0,input,check; i<form.elements.length; i++) {
			input = form.elements[i];
			if(checkReg.test(input.type)) {
				if(!check) check = input;
				if(input.checked) {
					checkedOne = true;
					break;
				}
			}
		}

		this.gui.displayError(check, !checkedOne);
		ClassName[checkedOne? 'remove':'add'](check.parentNode.parentNode, 'error');
		return (!checkedOne || !this.gui.validator.validateRequired(form))? false : true;
	},
	
	getContent:function(url, post) {
		if(post) {
			XMLHttp.sendAndLoad(post, url, this.scope(this.displayContent));
		} else {
			XMLHttp.load(url, this.scope(this.displayContent));
		}
	},

	getTravelType:function(node) {
		var adviceReg = /travel-advice/i;
		var type, typeReg = /advice-([a-z]+)/i;
		while(node) {
			if(adviceReg.test(node.className)) {
				type = typeReg.exec(node.id);
				return type? type[1] : "none";
			}
			node = node.parentNode;
		}
	},

	displayContent:function(xml) {
		this.display(false);
		var html = xml.getElementsByTagName("content")[0].firstChild.nodeValue;
		this.write(html);
		this.display(true);

		var calendars = getElementsByAttributeValue('class', 'calendar', this.container);
		for (var i=0; i<calendars.length; i++) {
			this.addCalendar(calendars[i]);
		}

		this.controller.toggleIEFrame(true, this.container);
	},

	addCalendar:function(element) {
		var calendar = new Calendar(element, {});
		calendar.setAction(this.scope(function(date){
			this.updateCalendar(element, date);
		}))
	},

	updateCalendar:function(element, date) {
		var inputs = element.parentNode.getElementsByTagName("input");
		inputs[0].value = date.getDate();
		inputs[1].value = date.getMonth() + 1; // month is zero based
		inputs[2].value = date.getFullYear();
		ClassName.remove(element.parentNode, 'display-calendar');
	},
	
	write:function(html) {
		this.content.innerHTML = html;
		new RoundedBoxes(this.content)
	}
});