/*
	Plugin Message v1.0.0
	http://imperavi.com/
 
	Copyright 2010, Imperavi Ltd.
	Dual licensed under the MIT or GPL Version 2 licenses.
*/
(function($){

	// Initialization
	$.message = function(message, options)
	{
		var obj = new Construct(message, options);
		obj.init();
		
		return obj;
	};	
	
	// Options and variables	
	function Construct(message, options) {

		this.opts = $.extend({
			className: 'imp_message',						
			duration: 20, // seconds
			once: false,			
			left: false,
			center: false
		}, options);
		
		this.opts.css = $.extend({
			zIndex: 70000,
			width: '170px',
			top: '20px',
			right: '20px',
			left: '20px'
		}, options);		
		
		this.message = message;
	};

	// Functionality
	Construct.prototype = {
		init: function()
		{	
			// Handlers			
			this.hdlClose = function() { this.close(); }.bind(this);
			
			if (this.opts.left) this.opts.css.right = 'auto';
			else if (this.opts.center)
			{
				this.opts.css.right = 'auto';
				this.opts.css.left = '50%';
				this.opts.css.marginLeft = '-' + this.normalize(this.opts.css.width)/2 + 'px';
			}
			else  this.opts.css.left = 'auto';
			
			// Build			
			this.growl = $('<div>').addClass(this.opts.className).html(this.message).css(this.opts.css);
			
			var growls = $('.' + this.opts.className);		
			if (growls.length && this.opts.once)
			{
				growls.first().html(this.message);
				return true;
			}
			
			if (growls.length)
			{
				var el = growls.last();
				this.growl.css('top', ($(el).height() + $(el).offset().top + 20) + 'px');
			}	
	
			$(this.growl).appendTo('body').click(this.hdlClose);	
			setTimeout(this.hdlClose, this.opts.duration*1000);
		},
		close: function()
		{
			$(this.growl).unbind('click');
			this.growl.fadeOut(function() { this._close(); }.bind(this));
		},
		_close: function()
		{
			var growls = $('.' + this.opts.className);
			var height = this.growl.height();
			
			if (growls.length)
			{
				var length = growls.length;
				var element = $(this.growl);
				
				for (i=0; i<length; i++)
				{
					var el = element.next('.' + this.opts.className);
					
					if (!$(el).length) break;
					
					$(el).css('top', ( $(el).offset().top - height - 20) + 'px');
					
					element = $(el);
				}
			
			}
		
			this.growl.remove();		
		},
		normalize: function(str)
		{
			return new Number(new String(str).replace('px',''));
		}			
	};
	
	// bind
	Function.prototype.bind = function(object)
	{
	    var method = this; var oldArguments = $.makeArray(arguments).slice(1);
	    return function (argument)
	    {
	        if (argument == new Object) { method = null; oldArguments = null; }
	        else if (method == null) throw "Attempt to invoke destructed method reference.";
	        else { var newArguments = $.makeArray(arguments); return method.apply(object, oldArguments.concat(newArguments)); }
	    };
	}		
	
})(jQuery);
