/**
 *	Dialog Controller for jQuery
 *	---------------------------------------------
 *	(c) 2008 Lost Boys - http://www.lostboys.nl
 *	Requires:
 *		jquery.js
 *		jquery.lb.utils.js
 */

(function($){

/**
 *	Settings
 *	--------------------------
 */

var ELEMENT_TITLE = 'h2',
	ELEMENT_BODY = 'p',

	DIALOG_OFFSET = 5,
	DIALOG_ORIENTATION = 'vertical',
	DIALOG_MODAL = false,

	OVERLAY_ACTIVE = true,
	OVERLAY_ID = 'overlay';

/**
 *	DialogController
 *	--------------------------
 */

function DialogController() {
	this.dialogTypes = {};
	this.dialogs = {};

	if(/msie 6/i.test(navigator.userAgent)){
		this.createIEFrame();
	}

	$(document).click(this.scope(this.tryClose));
	$(document).addRelation(/(^|\s)dialog-/i, this.displayDialog, this);
}

DialogController.prototype = {
	register:function(type, constructor) {
		this.dialogTypes[type] = constructor;
		return constructor;
	},

	displayDialog:function(link, dialogRel) {
		if(this.currentDialog) {
			this.currentDialog.toggle(false);
			this.toggleOverlay(false);
			this.toggleIEFrame(false);
		}

		var type = /dialog-([a-z0-9_-]+)/i.exec(dialogRel)[1];
		switch (type) {
			case 'close': break;
			case 'confirm': this.currentDialog.confirm(true); return true; break;
			case 'cancel': this.currentDialog.confirm(false); return true; break;
			default:
				var element = document.getElementById(dialogRel);
				return this.createDialog(element, link, type);
			break;
		}

		this.currentDialog = null;
		return true;
	},

	display:function(type, origin, title, body, action) {
		this.displayDialog(origin || document.body, 'dialog-' + type);
		this.currentDialog.write(title, body);
		this.setAction(action);
	},

	createDialog:function(element, link, type) {
		if(!element) return;
		var dialog = this.dialogs[type];
		if(!dialog) {
			var DialogClass = this.dialogTypes[type] || $.Dialog;
			dialog = new DialogClass(element, this, type);
		}

		this.currentDialog = this.dialogs[type] = dialog;
		dialog.setOrigin(link);
		dialog.toggle(true);
		this.toggleIEFrame(true, dialog.container);
		return dialog;
	},

	tryClose:function(e) {
		if(this.currentDialog) {
			var node = e.target;
			if(this.currentDialog.tryClose(node)) {
				this.toggleIEFrame(false);
			}
		}
	},

	toggleOverlay:function(toggle) {
		Overlay.toggle(toggle);
	},

	createIEFrame:function(){
		this.ieFrame = document.createElement("iframe");
		this.ieFrame.className = "cover-frame";
		this.ieFrame.frameBorder = 0;
	},

	toggleIEFrame:function(toggle, dialog) {
		if(this.ieFrame){
			var frm = this.ieFrame.style;
			if(toggle) {
				var parent = dialog.parentNode;
				parent.appendChild(this.ieFrame);
				frm.left = $(dialog).calculateLeft(parent) + "px";
				frm.top = $(dialog).calculateTop(parent) + "px";
				frm.width = dialog.offsetWidth + "px";
				frm.height = dialog.offsetHeight + "px";
				frm.display = "block";
			} else {
				frm.display = "none";
			}
		}
	},

	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}

/*
 *	Overlay
 *	-------------------------
 */

var Overlay = {
	init:function() {
		var overlay = document.createElement('div');
		overlay.id = OVERLAY_ID;
		this.container = document.body.appendChild(overlay);
	},

	setHeight:function() {
		var height = document.documentElement.scrollHeight || document.body.scrollHeight;
		var winHeight = window.innerHeight || document.documentElement.clientHeight;
		if(height < winHeight) {
			height = winHeight;
		}
		this.container.style.height = height + 'px';
	},

	toggle:function(toggle) {
		if(!this.container) this.init();
		this.setHeight();
		this.container.style.display = toggle? 'block' : 'none';
	}
}

/**
 *	Default Dialog
 *	--------------------------
 */

$.Dialog = function(element, controller, type) {
	this.container = element;
	this.controller = controller;
	this.type = type;

	this.modal = DIALOG_MODAL;
	this.overlay = OVERLAY_ACTIVE;
	this.orientation = DIALOG_ORIENTATION;
	this.offset = DIALOG_OFFSET;

	this.title = $(ELEMENT_TITLE, element)[0];
	this.body = $(ELEMENT_BODY, element)[0];
	this.vertical = /^vertical$/i;
}

$.Dialog.prototype = {
	setAction:function(action) { this.action = action; },
	setOrigin:function(origin) { this.origin = origin; },
	action:function() {},
	activate:function() {},

	toggle:function(toggle) {
		if(this.overlay || this.modal)
			this.controller.toggleOverlay(toggle);
		this.activate(toggle);
		this.display(toggle);
	},

	display:function(toggle) {
		var dialog = this.container;
		var origin = this.origin;
		var x = $(origin).calculateLeft();
		var y = $(origin).calculateTop();
		var css = dialog.style;

		css.display = toggle? 'block':'none';

		if(origin != document.body) {
			var w = dialog.offsetWidth;
			var h = dialog.offsetHeight;
			var ow = origin.offsetWidth;
			var oh = origin.offsetHeight;

			var vertical = this.vertical.test(this.orientation);
			var offsetH = vertical? 0 : DIALOG_OFFSET;
			var offsetV = vertical? DIALOG_OFFSET : 0;

			var availWidth = window.innerWidth || document.documentElement.clientWidth;
			var availHeight = window.innerHeight || document.documentElement.clientHeight;
			var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
			var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;

			var tx = (vertical? x : (x + ow)) + offsetH;
			var ty = (vertical? (y + oh) : y) + offsetV;
			if((tx + w) > (availWidth + scrollLeft)) tx = (vertical? (x + ow - w) : (x - w)) - offsetH;
			if((ty + h) > (availHeight + scrollTop)) ty = (vertical? (y - h) : (y + oh -h)) - offsetV;

			this.position(tx, ty);
		} else {
			this.center();
		}

		dialog.style.visibility = toggle? 'visible':'hidden';
	},

	position:function(x, y) {
		var css = this.container.style;
		css.left = x + 'px';
		css.top = y +'px';
	},

	center:function() {
	    if(!this.container.offsetWidth) return;
		var x = ((window.innerWidth || document.documentElement.clientWidth) - this.container.offsetWidth)/2;
		var y = (window.pageYOffset || document.documentElement.scrollTop) + ((window.innerHeight || document.documentElement.clientHeight) - this.container.offsetHeight)/2;
		if (y < 0) y = 0;
		$.Dialog.prototype.position.apply(this, [x, y]);
	},

	tryClose:function(node) {
		if(this.modal) return;
		while(node) {
			if(node == this.container || node == this.origin) return false;
			node = node.parentNode;
		}

		this.toggle(false);
		return true;
	},

	write:function(title, body) {
		if(title) this.title.innerHTML = title;
		if(body) this.body.innerHTML = body;
	},

	confirm:function(confirm) {
		if(this.action) this.action(confirm);
	},

	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}

/**
 *	Initialise
 *	--------------------------
 */

var dialogController = new DialogController();

$.extend($, {
	displayDialog:function(type) {
		return dialogController.displayDialog(document.body, type);
	},

	registerDialog:function(type, dialog) {
		return dialogController.register(type, dialog);
	}
});

$.extend($.fn, {
	displayDialog:function(type){
		dialogController.displayDialog(this[0], type);
		return this;
	}
});

/**
 *	End and init
 *	--------------------------
 */

})(jQuery);


/**
 *	custom: TooltipDialog
 *	--------------------------
 *	Origin nodevalue becomes title,
 *	origin title attribute becomes body.
 */

TooltipDialog = $.registerDialog('tooltip', Class.extend(
	$.Dialog,
	function() {
		// overridable properties
		this.modal = false;
		this.overlay = true;
		this.orientation = 'vertical';
		this.offset = 5;
	},{
	activate:function() {
		var title = this.origin.innerHTML.replace(/<[^>]+>/g, '');
		var body = this.origin.getAttribute("title");
		this.write(title, body);
	}
}));


/**
 *	custom: CenteredDialog
 *	--------------------------
 *	Centered insead of attached to origin
 */

CenteredDialog = $.registerDialog('alert', Class.extend(
	$.Dialog,
	function() {
	}, {
	
	position:function() {
		this.center();
	}
}));


/**
 *	custom: ModalDialog
 *	--------------------------
 *	Modal, user cannot ignore this dialog
 */

ModalDialog = $.registerDialog('warning', Class.extend(
	CenteredDialog,
	function() {
		this.modal = true;
	},
	null
));


/**
 *	custom: ExternalLinkDialog
 *	--------------------------
 *	Opts user a new window for the clicked link
 */

ExternalLinkDialog = $.registerDialog('external', Class.extend(
	$.Dialog,
	function() {
		this.orientation = 'horizontal';
		this.modal = true;
	},{

	confirm:function(confirm) {
		var href = this.origin.getAttribute("href");
		if(confirm) {
			window.open(href);
		} else {
			window.location = href;
		}
	}
}));

GalleryDialog = $.registerDialog('gallery', Class.extend(
	$.Dialog,
	function() {
	    this.modal = false;
	    this.overlay = false;
	    this.$image = $('.body .image img', this.container);
	    this.$image.bind("load", this.center.bind(this));
	}, {

	activate:function(toggle) {	
	  if(toggle) {
	    this.$image.attr("src", this.origin.href); 
	  } else {
	    this.$image.attr("src", "/Content/static/images/nix.gif");
	  }
	},

	position:function() {
		this.center();
	}

}));


/**
 *	custom: AjaxDialog
 *	--------------------------
 *	Executes origin href as post, expects an xml response
 */

AjaxDialog = $.registerDialog('ajax', Class.extend(
	$.Dialog,
	function() {
	},{

	toggle:function(toggle, uri) {
		if(toggle) {
			var href = uri || this.origin.href;
			var url = /[^?]+/.exec(href)[0];
			var post = /\?([^#]+)/.exec(href)[1];
			var that = this;
			$.post(
				url,
				post,
				function(data) {
					that.toggleResult(data, that);
				},
				'xml'
			);
		} else {
			$.Dialog.prototype.toggle.call(this, false);
		}
	},

	toggleResult:function(xml, instance) {
		instance.write(
			instance.getValue(xml.getElementsByTagName("title")[0]),
			instance.getValue(xml.getElementsByTagName("body")[0])
		);
		$.Dialog.prototype.toggle.call(this, true);
	},

	getValue:function(node) {
		return (node && node.firstChild)? node.firstChild.nodeValue : null;
	}
}));
