/**
 * jQuery messageBox plugin. Shows popup messages.
 *
 * Copyright (c) 2008 Roman Zaharenkov
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  *
  *	 Example:
  *		$('#mainForm').messageBox({messageType: 'Error'}, $.generateList, {messages: ['Please enter a name.', 
  *																												  'Please enter email in correct format.', 
  *																												  'Please select a date of birth.']});
  *																												  
  *		$('form').messageBox({messageType: 'Notification', width: 400, top: 500, autoClose: false}, 'Success');;	
  *	
  *	 Requirements:
  *		jquery.js
  *		jquery.domec.js -  jQuery DOMEC (DOM Elements Creator) 0.3.1
  *		jquery.timers.js - jQuery plug-in produces a friendlier and more intuitive timed event system.
  *		ui.core.js - jQuery ui core.
  *		ui.draggable.js - jQuery ui draggable plug-in.
  *		core.js - String and Function extension methods.
  *		
 */

(function($) {

	/**
	*  Generates DOM list by array of objects.
	*	
	*  Example:
	*  	generateList(['a', 'b', 'c'])
	*	
	*	 Output:	
	*  	<ul>		
	*  		<li>a</li>		
	*  		<li>b</li>		
	*  		<li>c/li>		
	*  	</ul>		
	*/
	$.extend({
		generateList: function(data) {
			errorsList = $.create('ul', {});
			for (i in data.list) {
				errorsList.append($.create('li', {}, data.list[i]));
			}
			return errorsList;
		}
	});

	$.extend({
		getScrollPosition: function(data) {
			if (typeof (window.pageYOffset) == 'number') {
				//Netscape compliant
				return { left: window.pageXOffset, top: window.pageYOffset };
			}
			else {
				if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
					//DOM compliant
					return { left: document.body.scrollLeft, top: document.body.scrollTop };
				}
				else {
					if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
						//IE6 standards compliant mode
						return { left: document.documentElement.scrollLeft, top: document.documentElement.scrollTop };
					}
				}
			}
		}
	});

	/**
	*	Message Box jQuery plug-in. Shows popup message boxes.
	*
	*	Parameters:
	*   topPositionElement - DOM element used for top alignment.
	*		settings - message box settings:		
	*			title - message box title
	*			messageType - type of message - {Error, Notification}
	*			autoClose - indicates whether message box will be closed automaticaly.
	*			autoCloseInterval - specifies time interval for auto closing.
	*			showCloseLink - indicates whether close link will be displayed.
	*			showKeptLink - indicates whether kept link will be displayed.
	*			showCloseLink - indicates whether close link will be displayed.
	*			hideEffect - specofies effect that be applied before message will be hided {'none', 'fadeOut'}
	*			width - specofies width of message box (content width by default).
	*			top - specofies top position of message box (0 by default).
	*		messageContent - content of the box. Can be string, DOM element or callback function passed.
	*		data - used with callback function for content building.
	*/
	$.fn.messageBox = function(topPositionElement, settings, messageContent, data) {

		settings = $.extend({}, $.fn.messageBox.defaults, settings);

		messageBox = function(parent, topPositionElement, settings, messageContent, data) {
			this.settings = settings;
			this.parent = $(parent);
			if (topPositionElement) {
				this.topPositionElement = $(topPositionElement);
			}
			this.messageContent = messageContent;
			this.data = data;
			this.body;
			this.title;
			this.keptLink;
			this.closeBox;
			this.timeRemaining = 0;
			this.listBox;
			this.isAutoclosingActive = false;
			this.fader;
			this.ie6 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 6.0") != -1);
		};

		messageBox.defaultWidth = 350;

		messageBox.maximumWidth = 600;

		messageBox.updateInterval = 1000;

		messageBox.autoCloseTimerLabel = 'autoClose';

		messageBox.updateTimerLabel = 'update';

		messageBox.prototype = {

			appendTitle: function(content) {
				content.prepend(
					this.title = $.create('div', { className: 'caption' }, [
						$.create('h2', {}, [
                            this.closeBox = $.create('div', { className: 'side' }, [
		                        $.create('img', { height: 9, width: 9, src: 'files/images/ico-x.gif', alt: 'close' })
		                    ]),
		                    settings.title
						]),
						$.create('div', { 'className': 'sep' })
					])
				);
				this.closeBox.bind('click', { errorWindow: this }, function(e) {
					e.data.errorWindow.hide();
				});
			},

			appendKeptLink: function() {
				this.timeRemaining = this.settings.autoCloseInterval / 1000;
				this.listBox.append(
					this.keptLink = $.create('p', { 'className': 'count-note' }, [
																		String.format('The window will be closed automatically after <strong class="Integer">{0}</strong> seconds or press ', this.timeRemaining),
																		link = $.create('a', { href: 'javascript:void(0)' }, 'hold'), ' this window.'
																	])
				);
				link.bind('click', { errorWindow: this }, function(e) {
					e.data.errorWindow.cancelAutoClose();
				});
			},

			appendCloseLink: function() {
				/*   // This close links is not needed. A closing red closs is already present at upper-right corner of message box
				this.listBox.append($.create('p', {'className' : 'CountNote', 'style' : 'text-align:right'}, [
				closeLink = $.create('a', {href: 'javascript:void(0)'}, 'Close')
				]));
				closeLink.bind('click', {errorWindow : this}, function(e){
				e.data.errorWindow.hide();
				});
				*/
			},

			buildWindowStyle: function() {
				style = {};
				width = this.settings.width;
				if (!width) {
					if (!$.browser.msie) {
						width = this.body.width();
					}
					else {
						width = messageBox.defaultWidth;
					}
				}
				if (width > messageBox.maximumWidth) {
					width = messageBox.maximumWidth;
				}
				style.width = String.format('{0}px', width);
				style.marginLeft = String.format('-{0}px', width / 2);
				if (this.topPositionElement && this.topPositionElement.length > 0) {
					topPosition = this.topPositionElement.position().top;
				}
				else {
					topPosition = this.settings.top;
				}
				if (!this.settings.blockScroll) {
					scrollPosition = $.getScrollPosition();
					if (scrollPosition) {
						topPosition = scrollPosition.top + topPosition;
					}
				}
				style.top = String.format('{0}px', topPosition);
				style.left = this.settings.left;
				return style;
			},

			buildWindow: function() {
				content = this.listBox = $.create('div', {});

				if (messageContent) {
					if (typeof messageContent == 'function') {
						this.listBox.append(messageContent.call(this, data));
					}
					else {
						this.listBox.append(messageContent);
					}
				}

				settings = this.settings;
				if (settings.showTitle) {
					this.appendTitle(content);
				}
				if (settings.autoClose) {
					if (settings.showKeptLink) {
						this.appendKeptLink();
					}
				}
				else {
					this.appendCloseLink();
				}

				this.body = $.create('div', { 'className': settings.containerClassName }, [
															popup = $.create('div', { 'className': 'pop-keys' }, [
																topElement = $.create('div', { 'className': 't png' }),
																middleElement = $.create('div', { 'className': 'content formA' }, [content]),
																bottomElement = $.create('div', { 'className': 'b png' })
															])
														]).prependTo(this.parent);

				if (settings.minWidth) {
					this.body.css({ minWidth: settings.minWidth });
					this.body.minSize({ width: settings.minWidth });
				}

				/*this.applySize(topLeftElement, topElement, topRightElement, middleElement, wrapperElement, bottomLeftElement, bottomElement, bottomRightElement);*/
				this.body.css(this.buildWindowStyle());
				this.body.draggable({
					handle: this.title,
					cursor: 'move',
					start: Function.createDelegate(this, this.cancelAutoClose)
				});

				if (settings.modal) {
					this.parent.prepend(this.fader = $.create('div', { className: settings.faderClass, style: String.format('height:{0}px;', $(document).height()) }, ''));
					//this.fader.bind('click', Function.createDelegate(this, this.hide));
					this.lockScroll();
				}

				arrowAreaElement = null;
				arrowElement = null;
				if (settings.showArrow) {
					arrowAreaElement = $.create('b', { 'className': 'arrow' }, [
				   arrowElement = $.create('i', {})
				  ]);
					popup.prepend(arrowAreaElement);
				}

				this.fixIE(topElement, middleElement, bottomElement);
			},

			applySize: function(topLeftElement, topElement, topRightElement, middleElement, wrapperElement, bottomLeftElement, bottomElement, bottomRightElement) {
				settings = this.settings;
				round = String.format('{0}px', settings.outerRound);
				topLeftElement.css({ height: round });
				topLeftElement.find('*').css({ height: round });
				topElement.css({ marginLeft: round, marginRight: round });
				topRightElement.css({ width: round, right: '-' + round });
				wrapperElement.css({ margin: String.format('0 {0}px', settings.innerRound) });
				bottomLeftElement.css({ height: String.format('{0}px', settings.outerRound + 2) });
				bottomLeftElement.find('*').css({ height: String.format('{0}px', settings.outerRound + 2) });
				bottomElement.css({ marginLeft: round, marginRight: round });
				bottomRightElement.css({ width: round, right: '-' + round });
			},

			fixIE: function(topElement, middleElement, bottomElement) {
				if (this.ie6) {
					settings = this.settings;
					this.closeBox.pngFix({ sizingMethod: 'scale' });
					//topLeftElement.pngFix({ sizingMethod: 'crop' });
					topElement.pngFix({ sizingMethod: 'scale' });
					//topRightElement.pngFix({ sizingMethod: 'crop' });
					//bottomLeftElement.pngFix({ sizingMethod: 'crop' });
					bottomElement.pngFix({ sizingMethod: 'scale' });
					//bottomRightElement.pngFix({ sizingMethod: 'crop' });
					middleElement.pngFix({ sizingMethod: 'crop' });
					if (settings.modal) {
						this.fader.append($.create('iframe', { height: this.fader.height(), width: this.fader.width(), src: 'javascript:false', frameBorder: 0, scroll: 'none' }));
						this.fader.pngFix({ sizingMethod: 'scale' });
					}
					else {
						this.body.append(helpFrame = $.create('iframe', { height: this.body.height(), width: this.body.width(), src: 'javascript:false', frameBorder: 0, scroll: 'none' }));
						helpFrame.css({ marginTop: -this.body.height() + 'px' })
					}

					if (settings.showArrow) {
						arrowAreaElement.pngFix({ sizingMethod: 'crop' });
						arrowElement.pngFix({ sizingMethod: 'scale' });
					}
				}
			},

			scrollHandler: function(e) {
				window.scrollTo(e.data.pos[0], e.data.pos[1]);
				return false;
			},

			lockScroll: function() {
				var a = [self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
								 self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop];
				if ($.browser.msie) {
					// Bad solution for IE
					//if (this.settings.blockScroll) {
					//  $(window).bind('scroll', {pos: a}, Function.createDelegate(this, this.scrollHandler));
					//}
				}
				else {
					if (this.settings.blockScroll) {
						$('body').css({ overflow: 'hidden' });
					}
				}
			},

			unlockScroll: function() {
				if ($.browser.msie) {
					// Bad solution for IE
					//if (this.settings.blockScroll) {
					//  $(window).unbind('scroll', Function.createDelegate(this, this.scrollHandler));
					//}
				}
				else {
					if (this.settings.blockScroll) {
						$('body').css({ overflow: 'scroll' });
					}
				}
			},

			show: function() {
				if (!this.body) {
					this.buildWindow();
				}
				this.body.show();
				settings = this.settings;
				this.activateAutoClosing();
			},

			hide: function() {
				if (this.body) {
					settings = this.settings;
					if ($.browser.msie) {
						this.destroy();
					}
					else {
						if (settings.hideEffect == 'none') {
							this.destroy();
						}
						if (settings.hideEffect == 'fadeOut') {
							this.body.fadeOut("slow", Function.createDelegate(this, this.destroy));
						}
					}
				}
			},

			destroy: function() {
				this.body.remove();
				if (this.settings.modal && this.fader) {
					this.fader.remove();
					this.unlockScroll();
				}
			},

			activateAutoClosing: function() {
				if (settings.autoClose) {
					this.isAutoclosingActive = true;
					$(this).oneTime(settings.autoCloseInterval, messageBox.autoCloseTimerLabel, function() {
						this.hide();
					});
					$(this).everyTime(messageBox.updateInterval, messageBox.updateTimerLabel, Function.createDelegate(this, this.updateLeptLink), this.timeRemaining);
				}
			},

			cancelAutoClose: function() {
				if (this.isAutoclosingActive) {
					$(this).stopTime(messageBox.autoCloseTimerLabel);
					this.keptLink.remove();
					this.appendCloseLink();
					this.isAutoclosingActive = false;
				}
			},

			updateLeptLink: function() {
				this.timeRemaining--;
				if (this.timeRemaining >= 0) {
					this.keptLink.html(String.format('The window will be closed automatically after <strong class="Integer">{0}</strong> seconds or press ', this.timeRemaining));
					link = $.create('a', { href: 'javascript:void(0)' }, 'hold');
					link.bind('click', { errorWindow: this }, function(e) {
						e.data.errorWindow.cancelAutoClose();
					});
					this.keptLink.append(link);
					this.keptLink.append(' this window.');
				}
			}
		};

		popupWindow = new messageBox($(this).get(0), topPositionElement, settings, messageContent, data);
		popupWindow.show();
		return popupWindow;
	};

	$.fn.messageBox.defaults = { showTitle: true,
		minWidth: 300,
		title: 'Message Box',
		messageType: 'Error',
		autoClose: true,
		autoCloseInterval: 5000,
		showCloseLink: true,
		showKeptLink: true,
		hideEffect: 'fadeOut',
		width: null,
		top: 0,
		left: '50%',
		modal: false,
		faderClass: 'Fader',
		className: 'Popup',
		containerClassName: 'popup-window',
		contentClassName: 'ListMode ListModeA',
		outerRound: 23,
		innerRound: 9,
		showArrow: false,
		arrowClass: 'arrow',
		blockScroll: false
	};

})(jQuery);