/**
 * pDialog
 * 
 * This is a wrapper plugin for jQuery UI dialog
 * p is for 'peppered'
 * 
 * Required (always):
 * 	 jQuery (currently tested and developed on 1.4.2) (development started on 1.3.2, will possibly break now on that)
 * 	 jQuery UI dialog (developed on 1.8) (development started on 1.7.2, may possibly still work on that)
 *
 * Required (sometimes):
 *   jquery.url (for when doing parentRefresh (special cases only))
 *   swfobject 2.2 (for type == 'swf')
 * 
 * Optional:
 * 	 $.log function in global namespace (needed for debugging)
 * 
 * @author AK | Peppered
 * @version 1.5.0
 * 
 */

;(function($) {

var dialogs = {};	// object to keep track of created dialogs
var $window = $(window);

$.pDialog = function(options){
		
	if ($.isPlainObject(options)) {
		// init (new) pDialog
	}
	else if (typeof options == 'string') {		
		if (arguments[1] == 'option') {
			// option setter
			// ... @todo
		}
		return;
	}
	
	/*
	 * global vars
	 */
	var dialogId = null, $uiWidget = {}, $dialog = {},
		uiWidget_oWidth, uiWidget_oHeight, uiWidget_oWidthP, uiWidget_oHeightP;
	
	/*
	 * Options
	 * All default UI Dialog options (including option events) will be passed through
	 * The same defaults are valid as the default dialog (http://jqueryui.com/demos/dialog/#options),
	 * with the following exceptions:
	 * 	modal: true		(pdialog will mostly be used this way)
	 *  autoOpen: false	(though pdialog opens itself after invoking, stuff like centering happens before the actual dialog open)
	 *  bgiframe: true
	 * 
	 */
	
	// specific pDialog options
	var pDialogOptions = {
		debug: false,
		
		id: '',								// each pdialog should have an unique id (used to respawn the dialog after a close for instance) 
											//   a HTML id attribute is assigned to the content <div/> as: {idPrefix}{id}
											// 
		type: null,							// dialog type, must be specified:
											//   message | confirmation | iframe | tabs | page | swf | image
											// 	
		extraClass: null,					// extra class to assign to dialog widget (format: ui-pdialog-TYPE-dialogClass)
											//   currently only implemented for type='iframe'
		idPrefix: 'uiDialog-',				// id-prefix
		buttonClass: null,					// adds this class (or classes) to the buttons in the widget buttonpane
		caption: null,						// caption for content. Currently only used for type=image
		autoResize: true,					// @todo (autoresize when window is resized)
		tabs: null,							// object defining the tabs (when type == 'tabs')
		useTabsAsHeader: false,				// instead of using default header displaying 'title', use the tabs as header (when type == 'tabs')	
		closeOnOutsideClick: false,			// takes precedence over bringInFocus, only works if modal == true
		closeOnInsideClick: false,			// closes dialog when clicked inside (useful for type=image)
		bringInFocusOnOutsideClick: true,	// centers the dialog, and highlights it. Only works if modal == true
		keepInDom: true,					// if true, a dialog close just hides the dialog, keeping it in the DOM (default behaviour)
											//   if false, the whole HTML structure will be removed, forcing a new generation of the dialog
		load: null,							// Resource to load/request (Ajax). For types 'iframe' and 'page'
		load_caching: null,					// Cache the loaded/requested page. The 'null' default makes jQuery choose itself what to do.
											// 
		iframe_header: null,				// snippet of HTML to put before the iframe (type==iframe)
		iframe_footer: null,				// snippet of HTML to put after the iframe (type==iframe)
		custom_header: null,				// snippet of HTML to use as header (instead of title) (type==iframe)
		
		hideTitleBar: false,				// if true, also means not draggable anymore
		keepCentered: true,					// if true, the dialog will stay centered in the viewport (creating viewport sb's when necessary)
		centeringTopDistance: 0,			// keep this distance (in px) from top of body (userfull for type=image, where titlebar is hidden, and close btn is positioned absolute
		hideCloseButton: false
	};
	
	// extend options
	options = $.extend({
		modal: true,
		autoOpen: false,
		buttons: {},
		bgiframe: true						// deprecated?
	}, pDialogOptions, options);
	
	// strip options from custom pdialog options, so we keep an object with purely UI dialog options
	var uiDialogOptions = $.extend({}, options);	// make a copy	
	for (var key in pDialogOptions) {
		delete uiDialogOptions[key];
	}
	
	var buttonExtras = {}; //@todo (be able to define different types/roles of buttons)
	
	/**
	 * Debugging
	 */
	if (options.debug && typeof $.log == 'function') {
		debug = $.log;
	}
	else {
		debug = function(){};
	}
	
	return spawnDialog(options.type);
	
	
	/**
	 * spawnDialog()
	 * 
	 */
	function spawnDialog(type) {
		dialogId = options.idPrefix + options.id;
		
		// Once, generate base HTML structure and append to body:
		if (!dialogs[options.id]) {
			
			// buttons
			uiDialogOptions.buttons = generateButtons();
			
			switch (options.type) {
				case 'tabs':
					createDialogWithTabs(dialogId);
					dialogs[options.id] = true;			// remember it has been created	
					break;
					
				case 'confirmation':
					$dialog = $('<div id="' + dialogId + '">' + options.content + '</div>');
					$('body').append($dialog.hide());					
					$dialog.dialog(uiDialogOptions);	// create the dialog
					
					$uiWidget = $dialog.parent();
					addWidgetClasses();	
					
					dialogs[options.id] = true;
					break;
					
				case 'message':
					$dialog = $('<div id="' + dialogId + '">' + options.content + '</div>');
					$('body').append($dialog.hide());
					$dialog.dialog(uiDialogOptions);
					
					$uiWidget = $dialog.parent();
					addWidgetClasses();
					
					dialogs[options.id] = true;
					break;
					
				case 'page':
					$dialog = $('<div id="' + dialogId + '"></div>');
					$('body').append($dialog.hide().addClass('ui-dialog-content-loading'));
					$dialog.dialog(uiDialogOptions);
					
					$.ajax({
						url: options.load,
						cache: options.load_caching,
						success: function(data){
							$dialog.html(data).removeClass('ui-dialog-content-loading');
						},
						error: function(XMLHttpRequest, textStatus, errorThrown){
							var errMsg = '';
							//debug(XMLHttpRequest.status);
							switch (XMLHttpRequest.status) {
								case 404:
									errMsg = '<p>Pagina niet gevonden.</p>';
									break;
								default:
									errMsg = '<p>Er heeft zich een onbekende fout voorgedaan.</p><p>Probeer het later nog eens.</p><p>Neem bij het aanhouden van deze fout a.u.b. contact met ons op.</p>';
							}
							$dialog.html(errMsg).removeClass('ui-dialog-content-loading');
							
						}
					});
					
					$uiWidget = $dialog.parent();
					addWidgetClasses();
					dialogs[options.id] = true;
					break;
					
				case 'image':
					// @todo proper sizing when w&h are undefined
					
					var $img = $('<img src="' + options.load + '" />')
						.load(function(){
							$dialog.removeClass('ui-dialog-content-loading');
						})
					;
					
					$dialog = $('<div id="' + dialogId + '">' + (options.caption != undefined ? ('<div class="caption">' + options.caption +  '</div>'): '') + '</div>');
					$dialog.prepend($img);
					
					$dialog.dialog(uiDialogOptions);
					
					$uiWidget = $dialog.parent();
					addWidgetClasses();
					
					dialogs[options.id] = true;
					break;
					
				case 'swf':
					if (typeof swfobject == 'undefined') {
						return false;
					}
					
					$dialog = $('<div id="' + dialogId + '"><div id="' + options.id + '"></div></div>');
									
					$('body').append($dialog.hide());
					
					var so_opts = $.extend(true, {}, {
						flashvars: {},
						params: {
							wmode: 'opaque',
							allowFullScreen: 'true',
							allowscriptaccess: 'always'
						},
						attributes: {},
						version: '9.0.0',
						expressInstallSwfurl: null,
						callbackFn: function(){}
					}, options.swfobject_config);
					
					var callbackFn = function(e){
						so_opts.callbackFn();
						$dialog.removeClass('ui-dialog-content-loading');
						if (!e.success) {							
							var $aClose = $('<a href="#">sluiten</a>').click(function(e){ $dialog.dialog('close'); e.preventDefault(); });
							var $p = $('<p/>').append($aClose);
							$('#'+e.id).html('<p>Flash content kon niet geladen worden.</p>').append($p);
						}
					};
										
					uiDialogOptions.width = so_opts.width;
					uiDialogOptions.height = so_opts.height;
					
					swfobject.embedSWF(so_opts.file, options.id, so_opts.width, so_opts.height, so_opts.version, so_opts.expressInstallSwfurl, so_opts.flashvars, so_opts.params, so_opts.attributes, callbackFn);
										
					uiDialogOptions.draggable = false;
					
					$dialog.dialog(uiDialogOptions);
					
					$uiWidget = $dialog.parent();
					addWidgetClasses();
					
					$uiWidget
						.draggable({ handle: '.ui-dialog-titlebar', codntainment: 'document' })
					;					
					
					dialogs[options.id] = true;					
					break;
					
				case 'iframe':
					$dialog = $('<div id="' + dialogId + '">' + options.iframe_header + '<iframe scrolling="auto" frameborder="0" src="' + options.load + '" />' + options.iframe_footer + '</div>');
					$('body').append($dialog.hide());
					$dialog.dialog(uiDialogOptions);
					
					$uiWidget = $dialog.parent();
					$uiWidget.addClass('ui-pdialog ui-pdialog-iframe' + (options.extraClass != null ? ' ui-pdialog-iframe-'+options.extraClass : ''));
					
					// custom title/header
					if (options.custom_header !== null) {
						$dialog.dialog('option', 'draggable', false);
						var $box = $('<div class="customHeader dragHandle"/>').append(options.custom_header);
						$uiWidget.find('.ui-dialog-titlebar .ui-dialog-title').replaceWith($box);
						$uiWidget
							.draggable({ handle: '.ui-dialog-titlebar .dragHandle', containment: 'document' })
						;						
					}
					
					dialogs[options.id] = true;
					break;
					
				default:
					debug('Aborting: Invalid dialog type');
					return false;
					
			}
			
			// Bind default events, and store options
			$dialog
				.bind('dialogopen',  function(e, ui) {
					debug('default dialogopen event triggered');
					
					if (type == 'tabs' && options.useTabsAsHeader) {
						//fn_useTabsAsHeader($(this), e, ui);
					}
					
					if (options.closeOnOutsideClick) {
						closeOnOutsideClick();
					}
					else if (options.bringInFocusOnOutsideClick) {
						bringInFocusOnOutsideClick();
					}
					
					if (type == 'iframe') {
						$dialog.addClass('ui-dialog-content-loading');
						$('body').addClass('ui-busy');
						$uiWidget.find('iframe').load(function(){
							$dialog.removeClass('ui-dialog-content-loading');
							$('body').removeClass('ui-busy');
						});
						$uiWidget.find('iframe').error(function(){
							$dialog.removeClass('ui-dialog-content-loading');
							$('body').removeClass('ui-busy');
						});
					}
					else if (type == 'image') {
						$dialog.addClass('ui-dialog-content-loading');
						if (options.closeOnInsideClick) {
							closeOnInsideClick($img);
						}
						$('html').addClass('ui-modalActive-image');
					}
					else if (type == 'swf') {
						$dialog.addClass('ui-dialog-content-loading');
						$('html').addClass('ui-modalActive-swf');
					}
					
					$('html').addClass('ui-modalActive');
					
					uiWidget_oWidth = $uiWidget.width();
					uiWidget_oHeigt = $uiWidget.height();
					uiWidget_oWidthP = $uiWidget.outerWidth();
					uiWidget_oHeightP = $uiWidget.outerWidth();
					
					center();
				})
							
				.bind('beforeclose',  function(e, ui) {
					debug('default beforeclose event triggered');
					if ($(this).dialog('option', '_parentRefresh') !== false) {
						if (options.parentRefresh) {
							$('body').addClass('ui-wait');
							e.preventDefault();
							// 'reload' parent (no location.reload() <> possible form submits)
							window.location = $.url.set(window.location.href, {fragment: ''});
						}
					}
				})
				
				.bind('dialogclose',  function(e, ui) {
					debug('default dialogclose event triggered');
					$('html').removeClass('ui-modalActive ui-modalActive-swf');
					if (options.keepInDom === false) {
						// remove from DOM
						debug('remove from DOM');
						$dialog = $('#'+dialogId);
						$dialog.dialog('destroy').remove();
						dialogs[options.id] = false;	
					}
				})
				
				.data('pdialog', {options: options})
			;	
		}
		else { // dialog already initialized
			$dialog = $('#'+dialogId);
			$uiWidget = $dialog.parent();
		}
		
		if (options.keepCentered) {
			$window.bind('resize', center);
		}
		
		// open/show the dialog
		// always center (if existing dialog has been opened after moved & closed)
		
		return $dialog
			//.dialog('option', 'position', 'center')
			.dialog('open')
		;
	
	}  /* /spawnDialog() */
	
	
	/**
	 * addWidgetClasses();
	 * 
	 * adds classes for the UI widget itself, as well to buttons
	 */
	function addWidgetClasses(){
		$uiWidget.addClass('ui-pdialog ui-pdialog-' + options.type +
			(options.extraClass != null ? ' ui-pdialog-'+options.type+'-'+options.extraClass : '') +
			(options.hideTitleBar === true ? ' ui-pdialog-hideTitleBar' : '')
		);
		if (options.buttonClass != null) {
			$uiWidget.find('.ui-dialog-buttonpane button').addClass(options.buttonClass);
		}
	}
	
	
	/**
	 * bringInFocusOnOutsideClick()
	 */
	function bringInFocusOnOutsideClick() {
		var $overlay = $uiWidget.prev('.ui-widget-overlay');		
		$overlay.click(function(){
			debug('event: ui-widget-overlay clicked');
			$uiWidget.effect('highlight');
			$dialog.dialog('option', 'position', 'center');
		});
	}
	
	/**
	 * closeOnOutsideClick()
	 */
	function closeOnOutsideClick() {
		var $overlay = $uiWidget.prev('.ui-widget-overlay');		
		$overlay.click(function(){
			$dialog.dialog('close');
		});
	}

	/**
	 * closeOnInsideClick()
	 */
	function closeOnInsideClick($target) {
		$target.click(function(){
			$dialog.dialog('close');
		});
	}
	
	/**
	 * generateButtons()
	 */
	function generateButtons() {
		var buttons = {};
		var i = 0;
		
		$.each(options.buttons, function(key, val) {			
			i++;
			buttonExtras[i] = { role: this.role };
			
			switch (this.action) {
				case 'cancel':
					buttons[key] = function() {
						var $this = $(this);
						$this.dialog('close');
					};
					break;
				case 'submit':
					buttons[key] = function() {
						debug('OK pressed, submit the form: ');
					};
					break;
				default:
					if (typeof this.action == 'function') {
						buttons[key] = this.action;
					}
					break;
			}
			
		});
		//debug(buttonExtras);
		return buttons;
	}
	
	
	/**
	 * createDialogWithTabs()
	 * 
	 * Available options per tab:
	 *    type		{String ('iframe')}		defaults to loading via Ajax
	 *    title		
	 *    load		{String}				the URL to load in tab
	 * 
	 */
	function createDialogWithTabs(dialogId) {
		
		var tabsHTML, tabListItemsHTML = '', tabContentsHTML = '', tabId;
			
		$.each(options.tabs, function(i, val){
			tabId = this.tabId = 'dialog-tab' + i;
			tabListItemsHTML += '<li><a href="#' + tabId + '">' + this.title + '</a></li>';	
			tabContentsHTML  += '<div id="' + tabId + '"></div>';
		});
		
		
		// Generate tabs HTML
		// This first needs to be appended to body, else the Tabs plugin can't/won't work correctly
		tabsHTML = '<div class="tabs" id="' + dialogId + '"><ul>' +
			tabListItemsHTML +
			'</ul><div class="richtext" id="tabDivsContainer">' +
			tabContentsHTML +
			'</div></div>'
		;
		
		// Append to body & hide
		$('body').append($(tabsHTML).hide());
		
		// Create the tabs and dialog
		var $dialog = $('#'+dialogId).tabs().dialog(uiDialogOptions);
		var $uiWidget = $dialog.parent();
		$uiWidget.addClass('ui-pdialog-dialogtabs');
		
		if (options.useTabsAsHeader) {
			var $uiTabsNav = $uiWidget.find('.ui-tabs-nav');			
			$dialog.dialog('option', 'draggable', false);			
			$uiWidget.find('.ui-dialog-titlebar').replaceWith($uiTabsNav);			
			$uiTabsNav
				.wrap('<div class="ui-tabs ui-dialog-titlebar"/>')
			;
			$uiWidget
				.draggable({ handle: '.ui-tabs-nav', cancel: '.ui-tabs-nav li', containment: 'document' })
			;
		}
		
		// load Ajax content
		$.each(options.tabs, function(i, val) {
			if (this.type == 'iframe') {
				var html = '<iframe src="'+this.load+'" frameborder="0"></iframe>';
				$('#' + this.tabId).addClass('pdialog-tab-iframe').html(html);
			}
			else {
				$('#' + this.tabId).load( this.load, null, function(responseText, textStatus, XMLHttpRequest){
					debug(responseText);
				} ); // gets cached in IE
			}
		});
	
	}
		
	/**
	 * center
	 * 
	 * Centers dialog in viewport
	 * Used when option keepCentered: true
	 * 
	 */
	function center(){
		var $subj = $uiWidget;
		
		var subj_oW = uiWidget_oWidth;
		var subj_oH = uiWidget_oHeight;
		var subj_oWp = uiWidget_oWidthP;
		var subj_oHp = uiWidget_oHeightP;
		
		// dimensions
		var vp_w = $window.width();
		var vp_h = $window.height();
		
		var subj_w =  $subj.outerWidth();
		var subj_h =  $subj.outerHeight();
				
		// calculate $subj left & top values
		var left = (vp_w/2 - subj_w/2) + $window.scrollLeft();
		if (left < 0) { left = 0; }
		
		var top = (vp_h/2 - subj_h/2) + $window.scrollTop();
		if (top < options.centeringTopMargin) { top = options.centeringTopMargin; }
		
		$subj.css({left: left, top: top});
	}
	
}; /* end of $.pDialog */


/**
 * public showNotice()
 * Shortcut function to use for (short) system messages/notices
 * 
 * @param {String} id				The unique id for pDialog
 * @param {String} notice_text		Plain-text String
 */
$.pDialog.showNotice = function(id, notice_text) {
	$.pDialog({
		id: id,			
		type: 'message',
		title: 'Let op!',
		content: '<div class="richtext"><p>' + notice_text+ '.</p><p>Klik op OK om door te gaan.</p></div>',
		bringInFocusOnOutsideclick: true,
		modal: true,
		buttons: {
			'OK': {
				action: 'cancel'
			}
		}
	});
};

})(jQuery); /* end of $.pDialog closure */
