/**
 * 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', {'className' : settings.messageType}, [
						  settings.title,
						  this.closeBox = $.create('div', {'className' : 'close'})
						])
					])
				);
				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' : 'CountNote'}, [
																		String.format('Window will be closed automatically in <strong class="Integer">{0}</strong> seconds. Click here to  ', this.timeRemaining),
																		link = $.create('a', {href: 'javascript:void(0)'}, 'keep'), ' 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 = $.create('div', {'className' : 'PopUpContent'}, [
															this.listBox = $.create('div', {'className' : this.settings.contentClassName})
													]);	
													
				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': 'PopUpBox ' + settings.className + settings.outerRound + '-' + settings.innerRound}, [
																topLeftElement = $.create('b', {'className': 'top'}, [
																	topElement = $.create('i', {}, [
																		topRightElement = $.create('ins', {})
																	])
																]),
																	middleElement = $.create('div', {'className': 'middle'}, [
																		wrapperElement = $.create('div', {'className': 'wrapper'}, [
																			$.create('div', {'className': 'bg'}, [content])																	
																		])
																]),
																bottomLeftElement = $.create('b', {'className': 'bottom'}, [
																	bottomElement = $.create('i', {}, [
																		bottomRightElement = $.create('ins', {})
																	])
																])																
															])				
														]).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(topLeftElement,
                    topElement,
                    topRightElement,
                    middleElement,
                    wrapperElement,
                    bottomLeftElement,
                    bottomElement,
                    bottomRightElement,
                    arrowAreaElement,
                    arrowElement);
			},
			
			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(topLeftElement, topElement, topRightElement, middleElement, 
			                  wrapperElement, bottomLeftElement, bottomElement, bottomRightElement,
			                  arrowAreaElement, arrowElement) {
        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('Window will be closed automatically in <strong class="Integer">{0}</strong> seconds. Click here to ', this.timeRemaining));
			    link = $.create('a', {href: 'javascript:void(0)'}, 'keep');
				  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 : 'PopUpContainer',
																contentClassName : 'ListMode ListModeA',
																outerRound : 23,
																innerRound : 9,
																showArrow : false,
																arrowClass : 'arrow',
																blockScroll : false};
	
})(jQuery);