/**
 * jGrowl 1.0.3
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Written by Stan Lemon <stanlemon@mac.com>
 * Last updated: 2008.06.11
 *
 * jGrowl is a jQuery plugin implementing unobtrusive userland notifications.  These 
 * notifications function similarly to the Growl Framework available for
 * Mac OS X (http://growl.info).
 *
 * Changes in 1.0.3
 * - Fixed bug with options persisting across notifications
 * - Fixed theme application bug
 * - Simplified some selectors and manipulations.
 * - Added beforeOpen and beforeClose callbacks
 * - Reorganized some lines of code to be more readable
 * - Removed unnecessary this.defaults context
 * - If corners plugin is present, it's now customizable.
 * - Customizable open animation.
 * - Customizable close animation.
 * - Customizable animation easing.
 * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
 *
 * Changes in 1.0.2
 * - All CSS styling is now external.
 * - Added a theme parameter which specifies a secondary class for styling, such
 *   that notifications can be customized in appearance on a per message basis.
 * - Notification life span is now customizable on a per message basis.
 * - Added the ability to disable the global closer, enabled by default.
 * - Added callbacks for when a notification is opened or closed.
 * - Added callback for the global closer.
 * - Customizable animation speed.
 * - jGrowl now set itself up and tears itself down.
 *
 * Changes in 1.0.1:
 * - Removed dependency on metadata plugin in favor of .data()
 * - Namespaced all events
 *
 * @todo	Group by header.
 */
(function($) {

	/** Raise jGrowl Notifications **/
	$.jGrowl = function( message , o ) {
		var o = $.extend({}, $.jGrowl.defaults, o);

		/** Startup jGrowl **/
		if ( $('div#jGrowl').size() == 0 ) $.jGrowl.startup();

		/** Create the Notification **/
		$('<div class="jGrowl"><div class="close">&times;</div><div class="header">' + o.header + '</div><div class="message">' + message + '</div></div>')
			.data("jGrowl", o).addClass(o.theme).children('div.close').bind("click.jGrowl", function() {
				$(this).unbind('click.jGrowl').parent().trigger('jGrowl.beforeClose').animate(o.animateClose, o.speed, o.easing, function() {
					$(this).trigger('jGrowl.close').remove();
				});
			}).parent().insertAfter('div#jGrowl div.jGrowl:last');

		/** Notification Actions **/
		$('div#jGrowl div.jGrowl:last').bind("mouseover.jGrowl", function() {
			$(this).data("jGrowl").pause = true;
		}).bind("mouseout.jGrowl", function() {
			$(this).data("jGrowl").pause = false;
		}).bind('jGrowl.beforeOpen', function() {
			o.beforeOpen.apply( this , [this,message] );
		}).bind('jGrowl.open', function() {
			o.open.apply( this , [this,message] );
		}).bind('jGrowl.beforeClose', function() {
			o.beforeClose.apply( this , [this,message] );
		}).bind('jGrowl.close', function() {
			o.close.apply( this , [this,message] );
		}).trigger('jGrowl.beforeOpen').animate(o.animateOpen, o.speed, o.easing, function() {
			$(this).data("jGrowl").created = new Date();
		}).trigger('jGrowl.open');
		
		/** Optional Corners Plugin **/
		if ( $.fn.corner != undefined ) $('div#jGrowl div.jGrowl:last').children().corner( o.corners );

		/** Add a Global Closer if more than one notification exists **/
		if ( $('div#jGrowl div.jGrowl:parent').size() > 1 && $('div#jGrowl div.closer').size() == 0 && $.jGrowl.defaults.closer != false ) {
			$('<div class="closer">[ close all ]</div>').addClass($.jGrowl.defaults.theme).appendTo("div#jGrowl").animate($.jGrowl.defaults.animateOpen, $.jGrowl.defaults.speed, $.jGrowl.defaults.easing).bind("click.jGrowl", function() {
				$(this).siblings().children('div.close').trigger("click.jGrowl");

				if ( $.isFunction( $.jGrowl.defaults.closer ) ) $.jGrowl.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] );
			});
		};
	};


	$.extend( $.jGrowl , {

		/** Default JGrowl Settings **/
		defaults: {
			header: 		'',
			sticky: 		false,
			position: 		'center',
			theme: 			'default',
			corners: 		'10px',
			check: 			1000,
			life: 			10000,
			speed: 			'normal',
			easing: 		'swing',
			closer: 		true,
			beforeOpen: 	function(e,m) {},
			open: 			function(e,m) {},
			beforeClose: 	function(e,m) {},
			close: 			function(e,m) {},
			animateOpen: 	{
				opacity: 	'show'
			},
			animateClose: 	{
				opacity: 	'hide'
			}
		},
	
		/** Interval Function **/
		interval:   null,

		/** Update the jGrowl Container, removing old jGrowl notifications **/
		update:	 function() {
			$('div#jGrowl div.jGrowl').each( function() {
				if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined && ($(this).data("jGrowl").created.getTime() + $(this).data("jGrowl").life)  < (new Date()).getTime() && $(this).data("jGrowl").sticky != true && 
					 ($(this).data("jGrowl").pause == undefined || $(this).data("jGrowl").pause != true) ) {
					$(this).children('div.close').trigger('click.jGrowl');
				}
			});

			if ( $('div#jGrowl > div.jGrowl:parent').size() < 2 ) {
				$('div#jGrowl div.closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
					$(this).remove();
				});
			};
			
			// If there are no more messages, let's tear down jGrowl.
			if ( $('div#jGrowl > div.jGrowl:parent').children().size() == 0 ) this.shutdown();
		},

		/** Setup the jGrowl Notification Container **/
		startup:	function() {
			this.interval = setInterval("jQuery.jGrowl.update()", this.defaults.check);
			$('<div id="jGrowl"><div class="jGrowl"></div></div>').addClass(this.defaults.position).appendTo('body');
		},

		/** Shutdown jGrowl, removing it and clearing the interval **/
		shutdown:   function() {
			clearInterval( this.interval );
			$('div#jGrowl').remove();
		}
	});

})(jQuery);