/*!
 * jQuery JavaScript plugin magicScroller v1.0
 * http://jquery.com/
 *
 * Copyright 2010, Jos� Edmundo Mart�nez Retama
 * GPL License
 * Date: Mon May 24 08:11:13 2010 -0500
 */
 ( function($) {
	//defins the function name
	//recive an object with atributes
    $.fn.magicScroller = function(params){

        //the default opctions
        $.fn.magicScroller.opc_default = {
                    displaytype:"one",
                    elementsByRow:3,
                    topSeparator:5,
                    leftSeparator:3,
                    delayTime:500,
                    animationTime:1000,
                    rowsDisplayed:2
        };

        // check if params are sent, else defaults is asigned
        opc = $.extend( $.fn.magicScroller.opc_default, params );
	//the final propieties are appended
	$.fn.magicScroller.needed = {
		displaytype: opc.displaytype, //how the elements will display
		positions:{}, // Contains the positions of all elements
		elements:opc.elements, //contains the elemts to scroll
		mask:opc.mask,//mascara de los elementos
		elementsPerRow:new Array(), //assigned elements per row
		elementsByRow: opc.elementsByRow, //number displayed elements by row
		topSeparator:opc.topSeparator, //number of pixels of top element separator
		leftSeparator:opc.leftSeparator, //number of pixels of left element separator
		totalRows: 0, //the total of rows created
		delayTime:opc.delayTime, //interval time of next element
		animationTime:opc.animationTime, //diring animation time
		rowsDisplayed:opc.rowsDisplayed, //how rows will display on each next action
		blockElements: new Array(), //the elements in blocks
		numberOfBlocks:0, //blocks generated ( this depends of rows displayed and elements per row )
		actualyDisplayed:0, //block actulally displayed
		stepScroll:0,  //the step of scroll
                prev:opc.prevbtn, // prev button
                next:opc.nextbtn //next button
	};


        $.fn.magicScroller.initializeAll = function(){
		//elements of actual row
		row = new Array();
		//elements of actual block
		block = new Array();
		//files counter
		counter = 0;
		//initiallize the elements block
		$.fn.magicScroller.needed.blockElements = new Array();
		//for each elements
		$.fn.magicScroller.needed.elements.each( function(i){
			//the element is in absolute position
			this.style.position = "absolute";
			//top style to the element
			this.style.top = $.fn.magicScroller.needed.positions.top[i] + 'px';
			//drop the margins
			this.style.margin = "0px";
			//asign the leftstyle to element ( initialize in negative value )
			this.style.left = '-' + $.fn.magicScroller.needed.positions.width[i] + 'px';
			//the opacity of the element is 0 for display in fadeIn efect
			this.style.opacity = '0';
			//get the mod for to know if is a new row
			mod = i % $.fn.magicScroller.needed.elementsByRow;
			if( mod == 0 ){
				//re initialize the row
				row = new Array();
				//increase the files counter for to know what row to manipulate
				counter++;
			}
			//add the element index to the row
			row.push( i );
			//verify if the rows counter is greater than rowsDisplayed, if true the elements block is completed
			if( counter > $.fn.magicScroller.needed.rowsDisplayed ){
				//add the block to the block elements
				$.fn.magicScroller.needed.blockElements.push( block );
				//reinitialize the block
				block = new Array();
				//the counter is 1
				counter = 1;
			}
			//the index of element is added to block
			block.push( i );
			//if is the last element per row or if is the last element
			if( mod == $.fn.magicScroller.needed.elementsByRow - 1 || i == $.fn.magicScroller.needed.elements.size() -1 )
			$.fn.magicScroller.needed.elementsPerRow.push(row); //se agrega la fila completa a el array
			//only if is the last element
			if( i == $.fn.magicScroller.needed.elements.size() -1 )
			$.fn.magicScroller.needed.blockElements.push(block);//se agrega block a blockelements
		});
		//
		//get the number of blocks
		$.fn.magicScroller.needed.numberOfBlocks = $.fn.magicScroller.needed.blockElements.length;
		//the actually block displayed
		$.fn.magicScroller.needed.actualyDisplayed = 0;
                display();
	};




        // returns the jQuery object list
        return this.each( function(){
                        //set the styles to mask
			$.fn.magicScroller.needed.mask.css({
                            position:"absolute",
                            'overflow-y':"hidden"

                        });
                        //get positions
			setPositions();
                        //initialize
			$.fn.magicScroller.initializeAll();
			$.fn.magicScroller.needed.prev.click( function(e){
				e.preventDefault();
				prevRow();
			});
			$.fn.magicScroller.needed.next.click( function(e){
				e.preventDefault();
				nextRow();
			});
        });


        //define the positions of elements
	function setPositions(){
		/**
		* left positions of all elements
		* @var Array
		*/
		var left = new Array();
		/**
		* top positions of all elements
		* @var Array
		*/
		var top = new Array();
		/**
		* width of all elements
		* @var Array
		*/
		var clientWidth = new Array();
		/**
		* height of all elemets
		* @var Array
		*/
		var clientHeight = new Array();
		/**
		* total of elements
		* @var int
		*/
		totalEl = $.fn.magicScroller.needed.elements.size();

		/**
		* top of next elements, starts 0
		* @var int
		*/
		ftop = 0;
		/**
		* left of next elements, starts 0
		* @var Array
		*/
		fleft = 0;
		//for each element
		$.fn.magicScroller.needed.elements.each( function(i){
			//add this width element to array
			clientWidth.push(this.clientWidth);
			//add this height element to array
			clientHeight.push(this.clientHeight);
			// if mod is 0, will add new row
			if( i % $.fn.magicScroller.needed.elementsByRow == 0 ){
				//the first element of row will be the leftSeparator only
				fleft = $.fn.magicScroller.needed.leftSeparator;
				//the top will increase, except if it�s the first row instead will be the top  separatyor only
				ftop += (i==0) ? $.fn.magicScroller.needed.topSeparator:this.clientHeight + $.fn.magicScroller.needed.topSeparator;
				$.fn.magicScroller.needed.totalRows++;
			}
			else //for each added element the left will increase
				fleft += $.fn.magicScroller.needed.leftSeparator + this.clientWidth;
			top.push(ftop); //this top element is added to array
			left.push(fleft); //this left element is added to array
		});
		//to positions object will add the propieties top, left, clientWith y clientHeight, width the elemets values
		$.fn.magicScroller.needed.positions.top = top;
		$.fn.magicScroller.needed.positions.left = left;
		$.fn.magicScroller.needed.positions.width = clientWidth;
		$.fn.magicScroller.needed.positions.height = clientHeight;
		//the step scroll is asigned
		$.fn.magicScroller.needed.stepScroll = $.fn.magicScroller.needed.positions.height[0] + $.fn.magicScroller.needed.topSeparator;
	}

	//show the elements by one
	function displayElementsByOne(){
		time = $.fn.magicScroller.needed.delayTime;
		$($.fn.magicScroller.needed.blockElements[ $.fn.magicScroller.needed.actualyDisplayed ]).each( function(i){
				index = parseInt(this);
				animationTime = $.fn.magicScroller.needed.animationTime;
				delayTime = $.fn.magicScroller.needed.delayTime;
				eval("setTimeout(\"$($.fn.magicScroller.needed.elements[" + index + "]).animate({left: $.fn.magicScroller.needed.positions.left[" + index + "] + 'px',opacity:'.6'}," + animationTime + ").delay(200).animate({opacity:1},'medium')\"," + ( time+=delayTime ) + ")");
		});
	}
	//show the elements by row
	function displayElementsByRow(){
		time = 0;
		animationTime = $.fn.magicScroller.needed.animationTime;
		delayTime = $.fn.magicScroller.needed.delayTime;
		elementsByRow = $.fn.magicScroller.needed.elementsByRow;
		$($.fn.magicScroller.needed.blockElements[ $.fn.magicScroller.needed.actualyDisplayed ]).each( function(i){
				index = parseInt(this);
				eval("setTimeout(\"$($.fn.magicScroller.needed.elements[" + index + "]).animate({left: $.fn.magicScroller.needed.positions.left[" + index + "] + 'px',opacity:'.6'}," + animationTime + ").delay(200).animate({opacity:1},'medium')\"," + ( ( i%elementsByRow==0 ) ? time+=delayTime:time ) + ")");
		});
	}
	//display elements by column
	function displayElementsByColumn(){

		animationTime = $.fn.magicScroller.needed.animationTime;
		delayTime = $.fn.magicScroller.needed.delayTime;
		elementsByRow = $.fn.magicScroller.needed.elementsByRow;
		time = new Array();
		timeA = 0;
		counter = -1;
		for(i = 0;i < elementsByRow;i++ )
			time.push( timeA+=delayTime );
		$($.fn.magicScroller.needed.blockElements[ $.fn.magicScroller.needed.actualyDisplayed ]).each( function(i){
				index = parseInt(this);
				mod = i % elementsByRow;
				counter = ( mod == 0) ? counter+1:counter;
				eval("setTimeout(\"$($.fn.magicScroller.needed.elements[" + index + "]).animate({left: $.fn.magicScroller.needed.positions.left[" + index + "] + 'px',opacity:'.6'}," + (animationTime + (counter * 200)) + ").delay(200).animate({opacity:1},'medium')\"," + ( time[mod] ) + ")");
		});
	}

	//display the prev row
	function prevRow(){
		$.fn.magicScroller.needed.actualyDisplayed--;
		if( $.fn.magicScroller.needed.actualyDisplayed >= 0 ){
			addtop =  ( $.fn.magicScroller.needed.actualyDisplayed == $.fn.magicScroller.needed.numberOfBlocks - 1 ) ? Math.ceil($.fn.magicScroller.needed.blockElements[ $.fn.magicScroller.needed.numberOfBlocks - 1 ].length / $.fn.magicScroller.needed.elementsPerRow) * $.fn.magicScroller.needed.stepScroll : $.fn.magicScroller.needed.rowsDisplayed * $.fn.magicScroller.needed.stepScroll;

			$.fn.magicScroller.needed.elements.animate({top:'+=' + addtop + 'px'});
		}
		else
			$.fn.magicScroller.needed.actualyDisplayed = 0;
	}
	//display the next row
	function nextRow(){
		if( $.fn.magicScroller.needed.actualyDisplayed < $.fn.magicScroller.needed.numberOfBlocks-1 ){
			addtop =  ( $.fn.magicScroller.needed.actualyDisplayed == $.fn.magicScroller.needed.numberOfBlocks - 1 ) ? Math.ceil($.fn.magicScroller.needed.blockElements[ $.fn.magicScroller.needed.numberOfBlocks - 1 ].length / $.fn.magicScroller.needed.elementsPerRow) * $.fn.magicScroller.needed.stepScroll : $.fn.magicScroller.needed.rowsDisplayed * $.fn.magicScroller.needed.stepScroll;
			$.fn.magicScroller.needed.elements.animate({top:'-=' + addtop + 'px'});
			$.fn.magicScroller.needed.actualyDisplayed++;
			display();
		}
		else
			$.fn.magicScroller.needed.actualyDisplayed = $.fn.magicScroller.needed.numberOfBlocks -1;
	}

	function display(){
		switch($.fn.magicScroller.needed.displaytype){
			case 'one':
				displayElementsByOne();
				break;
			case 'row':
				displayElementsByRow();
				break;
			case 'column':
				displayElementsByColumn();
				break;
		}
	}

    };
	
})(jQuery);

