(function($) {
	//
	// fadeGallery Plugin
	//
	$.fn.fadeGallery = function( options ){
		var opts = $.extend( {}, $.fn.fadeGallery.defaults, options );	
		
		return this.each( function() {
			var $this = $(this);
			var objs = Array(); //Array di oggetti di tutti i tag  LI { id : i, html : $(this)}
			var indexes = Array(); //Array indice contiene un array di Object { id: id, posX: null, posY: null, idEle: null  } dove idEle è l'id dell'elemento attuale
			var totEl = opts.rows * opts.cols; //Elementi da Visualizzare
			var widthImg, heightImg;
			//Init 
			function init() {
				var totCnt = $this.children('li').length; //Num. elementi attuali inseriti
				while( totEl > totCnt && opts.rows > 1 ){
					opts.rows--;
					totEl = opts.cols * opts.rows;
				}
				//Definisco UL position: relative, per posizionare in modo assoluti i tag LI
				$this.css( 'position', 'relative' );
				//Trovo la larghezza e altezza predefinita di ogni immagine
				widthImg = Number( parseInt( $('li:first img', $this).attr( 'width' ) ) );
				heightImg = Number( parseInt( $('li:first img', $this).attr( 'height' ) ) );
				//Sistema Altezza del UL
				var heightUl = (opts.rows * heightImg) + ( opts.marginTop * opts.rows );
				$this.css( 'height', heightUl + 'px' );

				
				//Metto tutti i tag <li> all'interno dell'array objs
				var i = 0;
				$this.children('li').each( function(){
					//Nascondo ogni elemento e lo definisco position Absolute
					$(this).css( {'position' : 'absolute', 'display' : 'none'} );
					var block = false;
					if( $(this).hasClass('yes') ) block = true;
					//Popolo l'oggetto objs
					objs.push( new Object({ id : i, blocked : block, html : $(this)}) );
					i++;
				});

				//Inizializza Array indexes a Random
				if( opts.randomPos ){
					for( var i = 0; i < totEl; i++ ){
						do{
							var rnd = parseInt( Math.random() * totEl );
							var ok = true;
							for ( ind in indexes ){ 
								if ( indexes[ind].id == rnd ){
									ok = false;
									break;
								}
							}
							if ( ok ) indexes.push( new Object( { id: rnd, posX: null, posY: null, idEle: null  } ) );
							
						}while( !ok );
					}
				}else{
					for( var i = 0; i < totEl; i++ ){
						indexes.push( new Object( { id: i, posX: null, posY: null, idEle: null  } ) );
					}
				}
				
				//Calcolo la x e y di ogni elemento per n(totEl) elementi
				var i = 0;
				for( var r = 0; r < opts.rows; r++ ){
					var m = 0;
					var posY = ( r * heightImg ) + (opts.marginTop * (r+1));
					for( var c = 0; c < opts.cols; c++ ){
						var posX = ( c * widthImg ) + (opts.marginLeft * m);
						var _indexes = getObjById( i, indexes );
						if( _indexes ){
							_indexes.posX = posX + 'px';
							_indexes.posY = posY + 'px';
						}
						i++;
						m++;
					}
				}
				
				//Inserisco tutti i primi n(totEl) attraverso fadeIn
				for( var i = 0; i < totEl; i++ ){
					var _objs = objs.shift();
					var _indexes = indexes.shift();
					var _indexesExt = fadeStart( _indexes, _objs );
					objs.push( _objs );
					indexes.push( _indexesExt );
				};
			};
			//
			// Private Function fadeOut
			// Prende in entrata posizione e oggetto e li nasconde
			//
			function fadeTimer(){
				//debug( objs );
				//debug( indexes );
				//Prendo elemento che c'è attualmente su indexes e lo faccio sparire
				var _indexes = indexes.shift();
				var _objs = getObjById( _indexes.idEle, objs );
				if( !_objs.blocked ){
					fadeOut( _indexes, _objs );
					_indexes.idEle = null;
					var _objs = objs.shift();
					while( _objs.blocked ){
						var _objs = objs.shift();
					}
					fadeIn( _indexes, _objs );
					_indexes.idEle = _objs.id;
				}
				objs.push( _objs );
				indexes.push( _indexes );
			}
			
			init();
			if( jQuery.timer )
				$(document).everyTime( opts.periodEvent, 'fadeGallery', fadeTimer, 0 );
			
			
		});
		
	};
	
	//
	// Plugin defaults
	//
	$.fn.fadeGallery.defaults = {
		debug : false,
		cols : 3,
		rows : 3,
		randomPos : true,
		marginTop: 10,
		marginLeft: 25,
		periodEvent : 1000 //5 Secondi
	};

	//
	// Private Function debug
	//
	function debug( message ) {
		if ( $.fn.fadeGallery.defaults.debug ){
			if ( window.console )
				console.debug( message );
			else alert( message )
		}
	};
	
	//
	// Private Function getObject By Id
	//
	function getObjById( _id, _obj ) {
		if( typeof _id != 'number' ){
			debug( 'getObjById: Il parametro passato _id deve essere un numero invece di un ' + typeof _id + ':' + _id );
			return null;
		}
		if( typeof _obj != 'object' ){
			debug ( 'getObjById: Il parametro passato _obj deve essere un object invece di un ' + typeof _obj );
			return null;
		}
		for( _i in _obj ){
			if( _obj[_i].id == _id)
				return _obj[_i];
		}
		return null;
		
	};
	
	//
	// Private Function fadeStart
	// Serve inizialmente per visualizzare i primi oggetti e inizializzare idEle
	// Prende in entrata _indexes, _obj e li visualizza tramite FadeIn; Resituisce il nuovo oggetto _indexes con idEle aggiornato
	//
	function fadeStart( _indexes, _obj ){
		if( typeof _indexes != 'object' && typeof _obg != 'object' ){
			debug( 'getObjById: Il parametro passato _obg e _indexes devono essere un object' );
			return null;
		}
		if( _obj ){
			$( _obj.html ).css( { left: _indexes.posX, top: _indexes.posY } );
			$( _obj.html ).fadeIn( "slow" );
			_indexes.idEle = _obj.id;
		}
		return _indexes
	}
	
	
	//
	// Private Function fadeIn
	// Prende in entrata _indexes, _obj e li visualizza tramite FadeIn; Resituisce il nuovo oggetto _indexes con idEle aggiornato
	//
	function fadeIn( _indexes, _obj ){
		if( typeof _indexes != 'object' && typeof _obg != 'object' ){
			debug( 'getObjById: Il parametro passato _obg e _indexes devono essere un object' );
			return null;
		}
		if( _obj ){
			$( _obj.html ).css( { left: _indexes.posX, top: _indexes.posY } );
			$( _obj.html ).fadeIn( "slow" );
		}
		return _indexes
	}
	
	//
	// Private Function fadeOut
	// Prende in entrata _indexes e li nasconde tramite FadeOut; Resituisce il nuovo oggetto _indexes con idEle null
	//
	function fadeOut( _indexes, _obj ){
		if( typeof _indexes != 'object' && typeof _obg != 'object' ){
			debug( 'getObjById: Il parametro passato _obg e _indexes devono essere un object' );
			return null;
		}
		//debug( _obj.html );
		if( _obj ){
			$( _obj.html ).css( { left: _indexes.posX, top: _indexes.posY } );
			$( _obj.html ).fadeOut( "slow" );
		}
		return _indexes
	}

	
})(jQuery);


