/*======================================================================*\
|| #################################################################### ||
|| # Package - YJ Mosaic News Slider                                    ||
|| # Copyright (C) 2010  Youjoomla LLC. All Rights Reserved.            ||
|| # Authors - Dragan Todorovic and Constantin Boiangiu                 ||
|| # This file is Copyrighted material                                  ||
|| # bound by Proprietary License of Youjoomla LLC                      ||
|| # for more information visit http://www.youjoomla.com/license.html   ||
|| # Redistribution and  modification of this software is prohibited    ||
|| # websites - http://www.youjoomla.com | http://www.yjsimplegrid.com  ||
|| #################################################################### ||
\*======================================================================*/
var YJ_Moz_Slider = new Class({
	initialize: function(options) {
		this.options = Object.extend({
			container: null,
			slides: null,
			images:null,
			infos: null,
			infosFx:{
				duration: 500,
				fx: Fx.Transitions.Sine.easeOut				
			},
			infosFxCss:{
				showFx:{
					'bottom':[-50, 0],
					'opacity':[0, 1]
				},
				hideFx:{
					'bottom':[0, -50],
					'opacity':[1, 0]
				},
				hiddenFx:{
					'bottom':-50,
					'opacity':0
				}
			},
			gridW:1,
			gridH:1,
			navigators: null,
			currentNavClass: 'selected',
			autoSlide: 0
		}, options || {});
		if( !this.options.container ) return;
		this.container = $(this.options.container);
		this.start();	
	},
	
	start: function(){
		var c = this.container;
		this.currentElement = 0;
		this.currentPiece = null;
		this.pieceDuration = 20;
		this.piecesOrder = null;
		this.slides = c.getElements(this.options.slides);
		this.images = c.getElements(this.options.images);
		this.infos = c.getElements(this.options.infos);
		this.navs = $$(this.options.navigators);
		
		this.prepareInfos();
		this.prepareGrid();
		this.prepareImages();
		this.pauseSlides();
		this.prepareNavigation();	
		
		/* start auto sliding */
		if( this.options.autoSlide ) this.startAuto();
		
	},
	
	pauseSlides: function(){
		if( !this.options.autoSlide ) return;
		
		$(this.options.container).addEvent('mouseenter', this.stopAuto.bind(this));
		$(this.options.container).addEvent('mouseleave', this.startAuto.bind(this));		
		
	},
	
	startAuto: function(){
		/* add to autoSlide time the time needed to play all pieces in image */
		var totalTime = this.options.autoSlide + ( this.slides[0]['pieces'].length * this.pieceDuration );			
		this.autoSlide = this.nextSlide.periodical( totalTime, this );
	
	},
	
	nextSlide: function(){
		
		var i = this.currentElement+1 >= this.slides.length ? 0 : this.currentElement+1;		
		this.changeSlide( i );
		
	},
	
	stopAuto: function(){
		
		$clear( this.autoSlide );
		
	},
	
	prepareInfos: function(){
		
		this.infos.each( function( el, i ){			
			this.infos[i]['fx'] = new Fx.Styles(el, {wait:false, duration:this.options.infosFx.duration, transition: this.options.infosFx.fx});
			if( this.currentElement !== i ){
				this.infos[i]['fx'].set(this.options.infosFxCss.hiddenFx);	
			}
		}.bind(this));
		
	},
	
	prepareNavigation: function(){
		
		this.navs.each( function(nav, i){
			
			if( i == this.currentElement )
				nav.addClass(this.options.currentNavClass);				
			
			nav.addEvent('click', function(event){
				new Event(event).stop();
				if( i == this.currentElement ) return;
				this.stopAuto();
				this.changeSlide( i );	
				//this.startAuto();
				
			}.bind(this));
			
		}.bind(this));
		
	},
	
	changeSlide: function( i ){
		
		if( i == this.currentElement ) return;
				
		this.currentPiece = null;
		this.piecesOrder = null;
		$clear(this.piecePeriodical);
		
		this.infos[this.currentElement]['fx'].start(this.options.infosFxCss.hideFx);
				
		this.slides[this.currentElement]['pieces'].each(function(p, i){
			p[1].set({'opacity': 1});
		});				
		
		this.slides.each( function(s, ind){
			var zIndex = 1;
			if( ind == this.currentElement )
				zIndex = 50;
			else if( ind == i )
				zIndex = 100;	
			s.setStyle('z-index', zIndex);
		}.bind(this));
		
		this.slides[i]['pieces'].each(function(p, i){
			p[1].set({'opacity': 0});
		});
		
		this.navs[this.currentElement].removeClass(this.options.currentNavClass);
		this.navs[i].addClass(this.options.currentNavClass);
		
		this.currentElement = i;
		this.piecesOrder = this.slides[i]['piecesOrder'];
		
		this.piecePeriodical = this.makeTransition.periodical(this.pieceDuration, this);
		
	},
	
	/* determines the width and height of each piece composing the image */
	prepareGrid: function(){
		var dim = this.container.getSize();
		this.sizeX = dim.size['x']/this.options.gridW;
		this.sizeY = dim.size['y']/this.options.gridH;
	},
	
	/* creates the pieces for each image */
	prepareImages: function(){
		this.images.each(function(container, index){
			
			var imgPath = container.getElement('img').getProperty('src');
			container.empty();
			var pieces = new Array();
			var line = 0;
			
			for( var t=0; t < this.options.gridW*this.options.gridH; t++ ){
				
				var w = (t%this.options.gridW)*this.sizeX;
				if( w == 0 && t > 0 ) line+=1;
				var h = line*this.sizeY;
				
				var piece = new Element('div').setStyles({
					'width':this.sizeX,
					'height':this.sizeY+1,
					'float':'left',
					'background-image':'url('+imgPath+')',
					'background-repeat':'no-repeat',
					'background-position':(-w)+'px '+(-h)+'px',
					'opacity': (index == this.currentElement ? 1 : 0),
					'class':'imagePiece'
				}).injectInside(container);
				
				var pieceFx = new Fx.Styles(piece, {wait:false, duration:500, transition:Fx.Transitions.linear});				
				pieces.include([piece, pieceFx]);
			}
			
			this.slides[index]['pieces'] = pieces;
			/* store pieces order on element */
			if( container.hasClass('straight') ){
				this.slides[index]['piecesOrder'] = this.straight( container.hasClass('reversed') );
			}else if( container.hasClass('swirl') ){
				this.slides[index]['piecesOrder'] = this.swirl( container.hasClass('reversed') );
			}else if( container.hasClass('diagonal') ){
				this.slides[index]['piecesOrder'] = this.diagonal( container.hasClass('reversed') );
			}else if( container.hasClass('random') ){
				this.slides[index]['piecesOrder'] = this.randomized();
			}else{
				this.slides[index]['piecesOrder'] = this.straight( container.hasClass('reversed') );	
			}
			
			
		}.bind(this))
	},
	
	makeTransition: function(){
		
		var c = this.slides[ this.currentElement ];
		
		if( !this.currentPiece ){
			this.currentPiece = 0;
		}else if( this.currentPiece >= this.options.gridW*this.options.gridH ){
			$clear( this.piecePeriodical );
			this.infos[this.currentElement]['fx'].start(this.options.infosFxCss.showFx);
			this.currentPiece = null;
			return;
		}	
		
		c['pieces'][this.piecesOrder[this.currentPiece]][1].start({'opacity':[1]});
		this.currentPiece+=1;		
	},
	/* swirl fx */
	swirl: function( reversed ){
		
		var orderPieces = [];
		var gridH = this.options.gridH;
		var gridW = this.options.gridW;

		var x = y = 1;
		var going = c = num = 0;
		var orderPieces = [];		
		var dowhile = true;
					
		while(dowhile) {
			
			num = (going==0 || going==2) ? gridW : gridH;			
			for ( i=1; i <= num; i++ ){
				
				orderPieces[c] = this.options.gridW*(x-1)+y-1;
				c++;

				if(i!=num){
					switch(going){
						case 0 : y++; break;
						case 1 : x++; break;
						case 2 : y--; break;
						case 3 : x--; break;					
					}
				}
			}
			
			going = (going+1)%4;

			switch(going){
				case 0 : gridW--; y++; break;
				case 1 : gridH--; x++; break;
				case 2 : gridW--; y--; break;
				case 3 : gridH--; x--; break;		
			}
			
			check = Math.max( gridH, gridW ) - Math.min( gridH, gridW );			
			if( gridW <= check && gridH <= check )
				dowhile = false;								
		}	
		
		return reversed ? orderPieces.reverse() : orderPieces;
	},
	/* straight fx */
	straight: function( reversed ){
		var orderPieces = [];
		for ( var i = 0; i < this.options.gridW*this.options.gridH; i++ ){
			orderPieces.include(i);
		};				
		return reversed ? orderPieces.reverse() : orderPieces;
	},
	/* diagonal fx */
	diagonal: function( reversed ){
	
		var gridH = this.options.gridH;
		var gridW = this.options.gridW;

		var c = 0; // cheia elementului
		var to = to2 = from = 1;
		var doWhile = true;
		var orderPieces = [];

		while(doWhile){			
			for( i = from; i <= to; i++ ){
				orderPieces[c] = (this.options.gridW * (i-1) + parseInt(to2-i+1))-1;
				c++;
			}
			
			to2++;			
			if( to < gridH && to2 < gridW && gridH < gridW ) to++;			
			if(to < gridH && gridH >= gridW ) to++;			
			if( to2 > gridW ) from++;			
			if( from > to ) doWhile= false;			
		}	
		
		return reversed ? orderPieces.reverse() : orderPieces;
		
	},
	/* random fx */
	randomized: function(){
		
		var orderPieces = this.straight();
		return this.shuffle( orderPieces );
		
	},
	/* helper function to shuffle array */
	shuffle : function(o){
		for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
		return o;
	}
});
