/**
 * 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() {
                var 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);
