/**
 * 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.x (for type == 'swf')
 * 
 * Optional:
 * 	 $.log function in global namespace (needed for debugging)
 * 
 * @author AK | Peppered
 * @version 1.4.2
 * 
 */

;(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: true,
		
		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
											// 	
		extraClass: null,					// extra class to assign to dialog widget (format: ui-pdialog-TYPE-dialogClass)
											//   currently only implemented for type='iframe'
		idPrefix: 'uiDialog-',				// id-prefix
		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,			// not yet implemented, only works if modal == true
		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)
		iframe_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)
	};
	
	// 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 = {};
	
	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();										
					
					$uiWidget.find('button').addClass('button');
					
					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 '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);
					
					
					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, so_opts.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 : ''));
					
					$uiWidget.find('.ui-dialog-titlebar-close').addClass('button'); // custom
								
					// 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.bringInFocusOnOutsideclick) {
						//debug($uiWidget)
						bringInFocusOnOutsideclick(e, ui);
					}
					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 == '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);
		}
		
		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();
	 */
	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' : '')
		);
	};
	
	
	/**
	 * bringInFocusOnOutsideclick()
	 */
	function bringInFocusOnOutsideclick(e, ui) {
		//var $dialog = $theDialogContent.parent();
		var $overlay = $uiWidget.prev('.ui-widget-overlay');		
		$overlay.click(function(){
			//debug('event: ui-widget-overlay clicked');
			//debug($theDialogContent);
			$uiWidget.effect('highlight');
			$dialog.dialog('option', 'position', 'center');
		});
	};
		
	
	/**
	 * 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_hPadding = parseInt($subj.css('paddingLeft')) + parseInt($subj.css('paddingRight')) ;
		var subj_hBorderW = parseInt($subj.css('borderLeftWidth')) + parseInt($subj.css('borderRightWidth')) ;
		
		var subj_vPadding = parseInt($subj.css('paddingTop')) + parseInt($subj.css('paddingBottom')) ;
		var subj_vBorderW = parseInt($subj.css('borderTopWidth')) + parseInt($subj.css('borderBottomWidth')) ;
		
		var subj_w = $subj.width() + subj_hPadding + subj_hBorderW;
		var subj_h = $subj.height() + subj_vPadding + subj_vBorderW;
				
		// calculate $subj left & top values
		var left = (vp_w/2 - subj_w/2) + $window.scrollLeft();
		if (left < 0) { left = 0; }
		//left = Math.max(left, margin);
		var top = (vp_h/2 - subj_h/2) + $window.scrollTop();
		if (top < 0) { top = 0; }
		//top = Math.max(top, margin);
		$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 */