/*
 * jQuery Runner - A content/image/anything slider
 * 
 * Author: Caio Oliveira
 * Version: Beta
 * Date: January	 2011
 */

(function($){
    var methods = {
        //MAIN SLIDE FUNCTION
        slider: function(slider_options,callback){
			var go = false;
			var back = false;
		    var run;
		    var auto_run;
			var menu_active_switcher;
			var switcher;
			var item;
		    var running;
			var isAuto = false;
			var isRunning;
			var clearRun;
			var qtdesqrs;
		    var $active;
		    var $next;
			var runanim;
			var ajaxInd = 1;
			var ajaxEnd = false;
            return this.each(function(){
                //DEFAULT CONFIGURATION
                var settings = {
                    first: 1,
					box: "#" + $(this).attr("id"),
                    slider: '.track',
                    item: '.runner',
                    auto: false,
                    width: 0,
                    height: 0,
                    invert: false,
                    transition_time: 300,
                    effect: 'slide',
                    columns: 5,
                    lines: 3,
                    random: false,
					loop: true,
					navigator: "#navigator",
					navigator_options: {
						nextButton: false,
						previousButton: false,
						listed: false
					}
                };
                $.extend(settings, slider_options);
                /******************
                 * VALORES PADRÃO *
                 ******************/
                //AMOUNT OF ELEMENTS
				isAuto = settings.auto;
				var item = settings.item;
				var slider_path = settings.box + " " + settings.slider;
				var item_path = settings.box+ " " + settings.slider + " " + settings.item;
                var qtde = $(item_path).size();
                //TRACK'S WIDTH
                if (settings['width'] == 0) {
                    $(item_path).each(function(){
                        if ($(this).width() > settings['width']) {
                            settings['width'] = $(this).width();
                        }
                    });
                }
                //TRACK'S HEIGHT
                if (settings['height'] == 0) {
                    $(item_path).each(function(){
                        if ($(this).height() > settings['height']) {
                            settings['height'] = $(this).height();
                        }
                    });
                }
				
                //INDEX
                var i = 1;
                $(item_path).each(function(){
                    $(this).attr('rel', i);
                    i++;
                });
                //FIRST AND NEXT ELEMENT ON ANIMATION
				$active = $(settings.item + ":first");
                
                if (!settings.random || settings.effect != "slide") 
                    $next = $active.next(item_path);
                else {
                    var rand = Math.floor((Math.random() * qtde) + 1);
                    $next = $(item_path + "[rel=" + rand + "]");
                }
				if(typeof menu_active_switcher == 'function'){
					menu_active_switcher();
				}
                
                /**************
                 * CSS NEEDED *
                 **************/
                //CSS DA BOX
                $(this).css({
                    position: 'relative',
                    overflow: 'hidden'
                });
                //CSS DA TRACK
				if((settings.width % 2) != 0)
					slider_width = ((settings['width']+1) * qtde);
				else
					slider_width = (settings['width'] * qtde);
                $(slider_path).css({
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    width: slider_width
                });
                //CSS DOS ITENS
                $(item_path).css({
                    'float': 'left'
                });
                
                //---->Fim do CSS
                
                /************
                 * SWITCHER *
                 ************/
                switcher = function(){
					if(settings.ajax)	$active = $(ajaxNext).children(settings.item);
                    else 				$active = $next;
					
                    if (!settings['random'] || settings.effect != "slide" || settings.ajax) {
						if(settings.ajax) {
							ajaxInd++;
							loadNextAjax(ajaxInd);
							if (ajaxEnd == true) {
								alert("cabo");
								ajaxInd = 1;
								loadNextAjax(ajaxInd);
							}
						}
                        $next = $active.next(item_path);
						if ($next.length == 0) {
							$(slider_path).show();
							$next = $(slider_path).children(item + ":first");
						}
                    }
                    else {
                        var rand = Math.floor((Math.random() * qtde) + 1);
                        $next = $(item_path + "[rel='" + rand + "']");
                    }
                };
                
                /***************************
                 * RUNNER'S ANIMATION CORE *
                 ***************************/
				var anim_interval = settings['auto']+settings['transition_time'];
                var slide = function(){
                    $(slider_path).animate({
                        'left': ((1 - $next.attr('rel')) * settings['width'])
                    }, settings['transition_time']);
                    switcher();
                };
                var loc_x;
                var buf = 0;
                var linha;
                var coluna;
                var linhas = settings['lines'];
                var colunas = settings['columns'];
                var $first_square;
				var $clone;
                qtdesqrs = linhas * colunas;
				anim_interval = qtdesqrs*30+300;
                
                var x_square = Math.round(settings.width / colunas);
                var y_square = Math.round(settings.height / linhas);
                
                $("<style type='text/css'>.square{white-space:nowrap; overflow:hidden; position:absolute; width:" + x_square + "px; height:" + y_square + "px; float:left;}.grid,.next{position:absolute;top:0;left:0; z-index:100000; width:" + x_square * colunas + "px; height:" + y_square * linhas + "px;}.next{z-index:99999;top:0;left:0;}</style>").appendTo("head");
                $("<div class='grid'></div>").appendTo($(this)); 
				$(settings.box+' .grid').hide();
				/********************
				 * Append functions *
				 ********************/
				var appendSquares = function(){
					$(settings.box + " .square").empty().stop(true,true);
					$(settings.box + " .grid").empty();
					for (i = 0; i < linhas; i++) {
	                    linha = ' l' + i;
	                    loc_y = y_square * i;
	                    for (var c = 0; c < colunas; c++) {
	                        coluna = ' c' + c;
	                        loc_x = c * x_square;
	                        $("<div class='square" + linha + coluna + "' style='left:" + loc_x + "px;top:" + loc_y + "px;'></div>").appendTo(settings.box + " .grid");
	                    }
	                }
				}
				
				var appendSquare = function(){
					$(settings.box + " .square").empty().stop(true,true);
					$(settings.box + " .grid").show().empty();
					$("<div class='square'></div>").appendTo(settings.box + " .grid");
				};
				
				var appendLines = function(){
					$(settings.box + " .square").empty().stop(true,true);
					$(settings.box + " .grid").empty();
					for (i = 0; i < linhas; i++) {
	                    linha = ' l' + i;
	                    loc_y = y_square * i;
	                    $("<div class='square" + linha + "' style='left:0px;top:" + loc_y + "px;'></div>").appendTo(settings.box + " .grid");
	                }
				};
				
				var appendColumns = function(){
					$(settings.box + " .square").empty().stop(true,true);
					$(settings.box + " .grid").empty();
					for (c = 0; c < colunas; c++) {
	                    coluna = ' c' + c;
	                    loc_x = x_square * c;
	                    $("<div class='square" + coluna + "' style='left:"+loc_x+"px;top:0px;'></div>").appendTo(settings.box + " .grid");
	                }
				};
				/*******************
				 * Reset functions *
				 *******************/
				var resetLines = function(){
					appendLines();
					$clonado = $active.clone().css({
						position: 'absolute'
					});
					$(slider_path).stop(true,true).css({
                        'left': ((1 - $next.attr('rel')) * settings['width'])+'px'
                    });
					$(settings.box + " .square").show().css({
						width: settings.width,
						height: y_square,
                        opacity: '1'
                    }).each(function(){
                        pos_top = -($(this).position().top);
                        $clonado.clone().appendTo($(this)).css({
                            top: pos_top
                        });
                    });
					$(settings.box+' .grid').show().css({
						width: settings.width,
						height: settings.height,
						top: 0,
						left: 0,
                        opacity: '1'
                    })
				};
				
				var resetColumns = function(){
					appendColumns();
					$clonado = $active.clone().css({
						position: 'absolute'
					});
					$(slider_path).stop(true,true).css({
                        'left': ((1 - $next.attr('rel')) * settings['width'])+'px'
                    });
					$(settings.box + " .square").show().css({
						width: x_square,
						height: settings.height,
                        opacity: '1'
                    }).each(function(){
                        pos_left = -($(this).position().left);
                        $clonado.clone().appendTo($(this)).css({
                            left: pos_left
                        });
                    });
				};

				var resetSquares = function(){
					appendSquares();
					$clonado = $active.clone().css({
						position: 'absolute'
					});
					$(slider_path).stop(true,true).css({
                        'left': ((1 - $next.attr('rel')) * settings['width'])+'px'
                    });
					$(settings.box + " .square").css({
						width: x_square,
						height: y_square,
                        opacity: '1'
                    }).each(function(){
                        pos_top = -($(this).position().top);
                        pos_left = -($(this).position().left);
                        $clonado.clone().appendTo($(this)).css({
                            top: pos_top,
                            left: pos_left
                        });
                    });
				};
				
				var resetSquare = function(){
					appendSquare();
					$clonado = $active.clone().css({
						position: 'absolute'
					});
					$(slider_path).stop(true,true).css({
                        'left': ((1 - $next.attr('rel')) * settings['width'])+'px'
                    });
					$(settings.box + " .square").css({
						opacity:1,
						width: settings.width,
						height: settings.height
                    });
                    pos_top = 0;
                    pos_left = 0;
                    $clonado.clone().appendTo($(settings.box + " .square")).css({
                        top: pos_top,
                        left: pos_left
                    });
				};
				/***********************
				 * Animation functions *
				 ***********************/
				//slide2 transition
				var slide2 = function(){
					resetSquares();
                                        
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            width: "hide",
							height: "hide",
							opacity:0
                        }, settings.transition_time);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0)
                            clearInterval(anim);
                    }, settings.transition_time/(qtde*20));
                    switcher();
                };
				//squares1 transition
				var squares = function(){
					resetSquares();
                                        
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            width: "hide",
							height: "hide",
							opacity:0
                        }, settings.transition_time);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0)
                            clearInterval(anim);
                    }, settings.transition_time/(qtde*20));
                    switcher();
                };
				
				//slide2 transition
				var squares2 = function(){
					resetSquares();
                                        
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            top:-x_square,
							left:-y_square,
							opacity:0
                        }, settings.transition_time);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0)
                            clearInterval(anim);
                    }, settings.transition_time/(qtde*20));
                    switcher();
                };
				
				//pixelate1 transition
				var pixelate = function(){
					resetSquares();
                    
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            opacity: 0
                        }, settings.transition_time);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0)
                            clearInterval(anim);
                    }, settings.transition_time/(qtde*20));
                    switcher();
                };
				
				//pixelate2 transition
				var npixelate = function(){
					resetSquares();
                    
                    $first_square = $(settings.box + " .square:last");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            opacity: 0
                        }, 600);
                        $first_square = $first_square.prev();
                        if ($first_square.length == 0) 
                            clearInterval(anim);
                    }, 20);
                    switcher();
                };
				var op;
				//lines1 transition
				var lines = function(){
				 $(settings.box+' .grid').show();
					if (back == true)	{op = settings.width; back=false;}
					else op = -settings.width;
					resetLines();
                    $first_square = $(settings.box+' .grid');
                    var anim = setInterval(function(){
                        $first_square.animate({
                            left:  op
                        }, (settings.transition_time/linhas)*3);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0) 
                            clearInterval(anim);
                    }, (settings.transition_time/linhas));
					switcher();
				};
				
				//columns1 transition
				var columns = function(){
					resetColumns();
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            height: 'hide'
                        }, (settings.transition_time/colunas)*3);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0) 
                            clearInterval(anim);
                    }, (settings.transition_time/colunas));
					switcher();
				};
				
				//columns2 transition
				var columns2 = function(){
					resetColumns();
                    $first_square = $(settings.box + " .square:first");
                    var anim = setInterval(function(){
                        $first_square.animate({
                            width: 'hide'
                        }, (settings.transition_time/colunas)*3);
                        $first_square = $first_square.next();
                        if ($first_square.length == 0) 
                            clearInterval(anim);
                    }, (settings.transition_time/colunas));
					switcher();
				};
				
				//columns3 transition
				var columns3 = function(){
					resetColumns();
                    $(settings.box + " .square").animate({
                            width: 'hide'
                        }, settings.transition_time);
					switcher();
				};
				
				//fade transition
				var fade = function(){
					resetSquare();
					$(settings.box + " .square").animate({
                            opacity: 0
                        }, settings.transition_time);
                    switcher();
                };
				
				//slipup transition
				var slipup = function(){
					resetSquare();
					$(settings.box + " .square").animate({
                            opacity: 0,
							top: -settings.width 
                        }, settings.transition_time);
                    switcher();
                };
				
				//slipdown transition
				var slipdown = function(){
					resetSquare();
					$(settings.box + " .square").animate({
                            opacity: 0,
							top: settings.width 
                        }, settings.transition_time);
                    switcher();
                };
				
				//This conditionals will check what is the effect chosen. If none, slider is default
				if (settings.effect == "pixelate1") 
					runanim = function(){
						pixelate();
					};
				else if (settings.effect == "pixelate2") 
					runanim = function(){
						npixelate();
					};
				else if (settings.effect == "slide2") 
					runanim = function(){
						slide2();
					};
				else if (settings.effect == "fade") 
					runanim = function(){
						fade();
					};
				else if (settings.effect == "slipup") 
					runanim = function(){
						slipup();
					};
				else if (settings.effect == "slipdown") 
					runanim = function(){
						slipdown();
					};
				else if (settings.effect == "squares1") 
					runanim = function(){
						squares();
					};
				else if (settings.effect == "squares2") 
					runanim = function(){
						squares2();
					};
				else if (settings.effect == "lines1") 
					runanim = function(){
						lines();
					};
				else if (settings.effect == "lines2") 
					runanim = function(){
						nlines();
					};
				else if (settings.effect == "columns1") 
					runanim = function(){
						columns();
					};
				else if (settings.effect == "columns2") 
					runanim = function(){
						columns2();
					};
				else if (settings.effect == "columns3") 
					runanim = function(){
						columns3();
					};
				else 
					runanim = function(){
						slide();
					};
				
				//RUN FUNCTION: Thats what gets things done
				run = function(){
					//Conditionals to check if the elements have personal transitions. It's checked by their classes
					if ($next.hasClass("fade")) fade();
					else if ($next.hasClass("slide2")) slide2();
					else if ($next.hasClass("slipup")) slipup();
					else if ($next.hasClass("slipdown")) slipdown();
					else if ($next.hasClass("pixelate1")) pixelate();
					else if ($next.hasClass("pixelate2")) npixelate();
					else if ($next.hasClass("squares1")) squares();
					else if ($next.hasClass("squares2")) squares2();
					else if ($next.hasClass("lines1")) lines();
					else if ($next.hasClass("columns1")) columns();
					else if ($next.hasClass("columns2")) columns2();
					else if ($next.hasClass("columns3")) columns3();
					else if ($next.hasClass("slide")) slide();
					else {
						runanim();
					}
					//To add a class to menu items
					if(typeof menu_active_switcher == 'function'){
						menu_active_switcher();
					}
					
					//Callback function (user can declare a function to happen everytime a transition happens
				    if (typeof callback == 'function') {
				        callback.call(this);
				    }

				};
                
                /*******************
                 * EXTRA FUNCTIONS *
                 *******************/
				//Automatic function
                if (settings['auto']) {
                    auto_run = function(){
						if (!isRunning) {
							isRunning = true;
							running = setInterval(function(){
								run();
							}, (anim_interval + settings.auto));
						}
                    };
                    auto_run();
					
					//Function used to stop the slider
					clearRun = function(){
						if (isRunning) {
							clearInterval(running);
							isRunning = false;
						}
					}
					
					//Hover stops the slider
					$(this).mouseover(function(){
						clearRun();
					}).mouseout(function(){
						auto_run();
					});
                }
									
					/********
					 * MENU *
					 ********/
					var menu_next_index;
					var $nav = $(settings.navigator);
					$nav.each(function(){
		                //GENERATES INDEX
		                var i = 1;
						/******************
						 * MAIN FUNCTIONS *
						 ******************/
		                if (settings.navigator_options.listed) {//IF MENU IS UNDER AN UL
							$(this).children('ul:first').children("li").each(function(){
								$(this).children('a').attr('rel', i);
								i++;
								$(this).children('a').click(function(){
									if (isAuto) 
										if (isRunning) {
											clearInterval(running);
											isRunning = false;
										}
									$next = $(item_path + "[rel='" + $(this).attr("rel") + "']");
									run();
									return false;
								});
							});
							$(this).children('ul:first').children("li:first").children("a").addClass("jrunner_active-menu-link");
						}
						else {
							$(this).children("a").each(function(){
								$(this).attr('rel', i);
								i++;
							});
							
							$(this).children("a").click(function(){
								if (isAuto) 
									clearRun();
								$next = $(item_path+"[rel='" + $(this).attr("rel") + "']");
								run();
								return false;
							});
							$(this).children('a:first').addClass("jrunner_active-menu-link");
						}
						/******************
						 * HOVER FUNCTION *
						 ******************/
						$(this).hover(function(){
							if(isAuto) 
								clearRun();
						},function(){
							auto_run();
						});
					});
					
					
					/**********************
					 * PREV/NEXT FUNCTION *
					 **********************/
					if(settings.navigator_options.previousButton != false){
						$(settings.navigator_options.previousButton).click(function(){
							back = true;
							if (isAuto) 
								clearRun();
							$next = $(item_path+"[rel='" + ($active.attr("rel")-1) + "']");
							if($next.length == 0) $next = $(item_path+":last");
							run();
							if($(settings.navigator_options.previousButton).parent(settings.navigator).length == 0 && isAuto) auto_run();
							return false;
						});
					}
					if(settings.navigator_options.nextButton != false){
						$(settings.navigator_options.nextButton).click(function(){
							if (isAuto) clearRun();
							run();
							if($(settings.navigator_options.nextButton).parent(settings.navigator).length == 0 && isAuto) auto_run();
							return false;
						});
					}
					
					/****************************
					 * ACTIVE SWITCHER FUNCTION *
					 ****************************/
					menu_active_switcher = function(){
						menu_next_index = $active.attr('rel');
						$(".jrunner_active-menu-link").removeClass("jrunner_active-menu-link");
						$(settings.navigator+" a[rel='"+menu_next_index+"']").addClass("jrunner_active-menu-link");
					}
            });//---->end of "each"
        }//---->end of slider
    }//---->Methods end
    /*************************
     * MAIN FUNCTION HANDLER *
     *************************/
    $.fn.runner = function(method){
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        else 
            if (typeof method === 'object' || !method) {
                return methods.slider.apply(this, arguments);
            }
            else {
                $.error('"' + method + '" not available on Runner plugin');
            }
    };
})(jQuery);
