/**
 * Diese Version ist eine abgeänderte Version des jQuery infinitecarousels
 * Diese vor Aktualisierung bitte vorher mit einem Entwickler absprechen
 * 
 * !!! bei singleside nur wrapper mit doppelter Bildbreite verwenden Bsp. 391px Bildbreite, 782px Wrapperbreite und es müssen mind. 2 Bilder verwendet werden !!!
 * 
 * 	slidingWidth:		auto			scrollt die ganze Container Breite
 * 						single			scrollt ein Bild
 * 						singleside		scrollt ein Bild, beginnt aber zu einem Teil des Bildes mit animation für rechtes und
 * 										linkes Bild zum ganz ansehen
 * 	animationTime		Zeit in Millisekungen
 * 	selector
 * 
 * Autoscrolling:
 *  $(document).ready(function () {
 *      // THIS IS NEW CODE FOR THE AUTOMATIC INFINITE CAROUSEL
 *      var autoscrolling = true;
 *      
 *      $('.infiniteCarousel').infiniteCarousel({
 *   	   selector: 		"li",
 *   	   animationTime: 	1500,
 *   	   slidingWidth:	"single"
 *      }).mouseover(function () {
 *          autoscrolling = false;
 *      }).mouseout(function () {
 *          autoscrolling = true;
 *      });
 *       
 *      
 *      setInterval(function () {
 *          if (autoscrolling) {
 *              $('.infiniteCarousel').trigger('next');
 *          }
 *      }, 5000);
 *  });
 */

	$.fn.infiniteCarousel = function (options) {
	   var defaults = {
    		   selector: 		"div",		/* Selector, ab welchem die Bild Elemente anfangen (z.B. div, li...) */
    		   animationTime:	500,		/* Zeit in Millisekunden wie lange neues Bild zum sliden braucht */
    		   slidingWidth:	"auto"		/* gesamte Breite sliden oder nur Bildweise, auto, single oder singleside */
       };
       
       var options = $.extend(defaults, options);		// defaults überschreiben
	   
	   // 
       function repeat(str, num) {
           return new Array( num + 1 ).join( str );
       }

       // gehe Elemente durch
       return this.each(function () {
           //////////////////
           // Members
           //////////////////
    	   
           var $wrapper = $('> div', this).css('overflow', 'hidden'),		// wrapper holen
           $slider = $wrapper.find('> ul').width(9999),						// slider holen
           $items = $slider.find('> ' + options.selector),					// Elemente holen (Bilder)
           $single = $items.filter(':first'),		// erstes Element (Bild) holen
           singleWidth = $single.outerWidth();		// Bildbreite bestimmen
           var bClickedBack = false;				// wurde Slider back geklickt
           var bClickedForward = false;				// wurde Slider forward geklickt

    	   visible = Math.ceil($wrapper.innerWidth() / singleWidth); // note: doesn't include padding or border
           currentPage = 1;		// aktuelle Seite setzen
           
           //////////////////
           // Logik
           //////////////////
           
       	   // Berechnung der Scrollbaren Seiten
           if(options.slidingWidth == "auto") {
        	   pages = Math.ceil($items.length / visible);
           }
           else {
       	       pages = Math.ceil($items.length - 1 / visible);
           }

           // 1. Pad so that 'visible' number will always be seen, otherwise create empty items
           if (($items.length % visible) != 0 && options.slidingWidth == "auto") {
        	   var element = '<' + options.selector + ' class="empty"></li>';
               $slider.append(repeat(element, visible - ($items.length % visible)));
               $items = $slider.find('> ' + options.selector);
           }

           // 2. Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
           $items.filter(':first').before($items.slice(- visible).clone().addClass('cloned'));
           $items.filter(':last').after($items.slice(0, visible).clone().addClass('cloned'));
           $items = $slider.find('> ' + options.selector); // reselect
           
           // Button für fade setzen
           // 3. Set the left position to the first 'real' item
           var scrollPosition = 0;
           if(options.slidingWidth == "singleside") {
        	   setAWithFadeKlass($items);		// Buttons zum faden setzen
        	   // Bild mittig positionieren bei halbschritt
        	   scrollPosition = singleWidth - ($wrapper.innerWidth() - singleWidth) / visible;
           }
           else if(options.slidingWidth == "single") {
        	   scrollPosition = singleWidth * visible;
           } else {
        	   scrollPosition = singleWidth * visible;
           }
           
           $wrapper.scrollLeft(scrollPosition);		// Startposition
           if(options.slidingWidth == "singleside")
        	   $wrapper.after('<a class="arrow forward"></a>');		// Slide Buttons
           else
        	   $wrapper.after('<a class="arrow back"></a><a class="arrow forward"></a>');		// Slide Buttons
           
           //////////////////
           // Funktionen
           //////////////////
           
           // 4. paging function
           function gotoPage(page) {
               var dir = page < currentPage ? -1 : 1,
                   n = Math.abs(currentPage - page);
               
//               console.log("dir > " + dir + " page > " + page + " currentPage > " + currentPage + " n > " + n);
               
               // Berechnung wie weit geslidet werden soll
               if(options.slidingWidth == "auto") {
                   left = singleWidth * dir * visible * n;
               }
               else {
            	   left = singleWidth * dir * n;
               }

//               console.log('left > ' + left);
               
               $wrapper.filter(':not(:animated)').animate({
                   scrollLeft : '+=' + left
               }, options.animationTime, function () {
            	   // alle Elemente wieder zum Anfang
            	   var scrollPage = 0;
                   if (page == 0) {
                	   // Sonderbehandlung singleside
                	   if(options.slidingWidth == "singleside") {
                		   scrollPage = singleWidth * visible * pages - scrollPosition;
                	   }
                	   else if(options.slidingWidth == "single") {
                		   scrollPage = singleWidth * visible * pages - singleWidth * visible;
                	   } else {
                		   scrollPage = singleWidth * visible * pages;
                	   }
                	   
                	   $wrapper.scrollLeft(scrollPage);
            		   page = pages;
//            		   console.log('page == 0');
                   } else if (page > pages) {                	   
                	   if(options.slidingWidth == "singleside")
                		   removeAWithFadeKlass($items);		// fade Button entfernen
                	   
                	   $wrapper.scrollLeft(scrollPosition);
                       // reset back to start position
                       page = 1;
//                       console.log('page > pages ' + pages + ': ' + scrollPage);
                   } 
//                   console.log('wrapper.innerWidth() > ' + $wrapper.innerWidth() + ' scrollPosition > ' + scrollPosition + ' visible > ' + visible);
   
                   currentPage = page;
               });

               // Fader Buttons richtig setzen, nur bei singleside
               if(options.slidingWidth == "singleside") {
            	   setFadeKlass($items);		// Verhalten zum faden ändern
               }
               
               return false;
           }
           
           // entfernt fade Buttons
           function removeAWithFadeKlass(items) {
        	   // jedes Element
        	   items.each(function() {
        		  $( this ).find('.arrowfade').remove();	// fade Button entfernen 
        	   });
        	   setAWithFadeKlass($items);
           }
           
           // class setzen zum faden
           function setAWithFadeKlass(items) {
	           var klass = "";
	           var nCount = 0;
	           
	           // gehe jedes Element durch (Bilder)
	           items.each(function() {
	        	   if(nCount == 0) {
	        		   klass = "faderight";
	        	   }
	        	   else if(nCount == 2) {
	        		   klass = "fadeleft";
	        	   } else {
	        		   klass = "";
	        	   }
	        	   
	        	   $( this ).append('<a class="arrowfade ' + klass + '"></a>');		// Button zum faden hinzufügen
	        	   nCount++;
	           });
           }
           
           // setze Klasse zum faden
           function setFadeKlass(items) {
//        	   console.log('setFadeKlass(...)');
        	   
        	   // Jedes Bild durchlaufen
        	   var nCount = 0;
        	   var nSetterLeft = 0;
        	   var nSetterRight = 0;
        	   var bSetRight = false;
        	   var bSetLeft = false;
        	   var bClearRight = false
        	   var bClearLeft = false
               items.each(function() {
            	   aElement = $( this ).find('a.arrowfade');		// Button finden
            	   aElement.unbind('click');		// Klick Handler entfernen
            	   
            	   // Button style entfernen
            	   if(aElement.hasClass('faderight')) {
            		   aElement.removeClass('faderight'); 
            		   if(bClickedForward)
            			   nSetterRight = nCount + 1;
            		   
            		   bClearRight = true;
//            		   console.log('remove faderight: nSetterRight > ' + nSetterRight);
            	   }
            	   else if(aElement.hasClass('fadeleft')) {
            		   aElement.removeClass('fadeleft');
        			   if(bClickedForward)
        				   nSetterLeft = nSetterRight + 2;
        			   
//        			   console.log('remove fadeleft: nSetterLeft > ' + nSetterLeft);
        			   bClearLeft = true;
            	   }
            	   
            	   // faderight setzen
            	   if(nCount == nSetterRight && !bSetRight && bClearRight) {
            		   aElement.addClass('faderight');
//            		   console.log('set faderight: nCount > ' + nCount);
            		   // Klick Handler setzen
            		   $('.faderight', this).click(function(){
            			  fadeRight(this); 
            		   });
            		   
            		   bSetRight = true;
            	   }
            	   
            	   // fadeleft setzen
            	   if(nCount == nSetterLeft && !bSetLeft && bSetRight && bClearLeft) {
            		   aElement.addClass('fadeleft');
//            		   console.log('set fadeleft: nCount > ' + nCount);
            		   // Klick Handler setzen
            		   $('.fadeleft', this).click(function(){
            			   fadeLeft(this); 
            		   });
            		   
            		   bSetLeft = true;
            	   }
//            	   console.log(nCount);
            	   nCount++;
               });
           }
           
           // fadet ein übergeordnetes Objekt nach links oder rechts je nach Klassen
           function fadeLeft(objekt) {
        	   // Überprüfen, wohin gefadet werden soll
        	   if($(objekt).hasClass('fadeleft')) {
            	   // Ausfahren nach links
            	   $(objekt).parent().animate({
            		   "margin-left"	: "-=" + singleWidth / 2 + "px"		// halbe Bildbreite 
            	   }, "slow");
            	   $(objekt).removeClass("fadeleft").addClass("faderight");		// Klasse entfernen und faderight setzen
            	   $('a.forward').hide();		// verhindern, das gescrollt wird wenn ausgeklappt
        	   } else {
            	   // Ausfahren nach rechts
            	   $(objekt).parent().animate({
            		   "margin-left"	: "+=" + singleWidth / 2 + "px" 		// halbe Bildbreite
            	   }, "slow");
            	   $(objekt).removeClass("faderight").addClass("fadeleft");		// Klasse entfernen und fadeleft setzen
            	   $('a.forward').show();
        	   }
           }
           
           // fadet ein Objekt nach links oder rechts je nach Klassen
           function fadeRight(objekt) {
        	   // Überprüfen, wohin gefadet werden soll
        	   if($(objekt).hasClass('faderight')) {
        		   // Ausfahren nach links
        		   $(objekt).parent().animate({
        			   "margin-left"	: "+=" + singleWidth / 2 + "px"		// halbe Bildbreite 
        		   }, "slow");
        		   $(objekt).removeClass("faderight").addClass("fadeleft");		// Klasse entfernen und faderight setzen
        		   $('a.forward').hide();		// verhindern, das gescrollt wird wenn ausgeklappt
        	   } else {
        		   // Ausfahren nach rechts
        		   $(objekt).parent().animate({
        			   "margin-left"	: "-=" + singleWidth / 2 + "px" 		// halbe Bildbreite
        		   }, "slow");
        		   $(objekt).removeClass("fadeleft").addClass("faderight");		// Klasse entfernen und fadeleft setzen
        		   $('a.forward').show();		// verhindern, das gescrollt wird wenn ausgeklappt
        	   }
           }
           
           //////////////////
           // Event Handler
           //////////////////
           var zeit = new Date();		// zum verhindern von Doppelklicks
           var ms = 0;
           
           // 5. Bind to the forward and back buttons
           $('a.back', this).click(function () {
        	   // wurde schon geklickt
        	   bClickedBack = true;
        	   bClickedForward = false;
        	   
               return gotoPage(currentPage - 1);
           });
           
           $('a.forward', this).click(function () {
        	   bClickedBack = false;
        	   bClickedForward = true;
        	   
               return gotoPage(currentPage + 1);
           });
           
           // wenn fadeleft gekclickt wurde
           $('a.fadeleft', this).click(function () {
        	   fadeLeft(this);		// Animation starten
           });
           
           // wenn faderight geklickt wurde
           $('a.faderight', this).click(function () {
        	   fadeRight(this);		// Animation starten
           });
           
           //////////////////
           // Trigger Events //
           ////////////////////
           
           // create a public interface to move to a specific page
           $(this).bind('goto', function (event, page) {
               gotoPage(page);
           });
           
           // THIS IS NEW CODE FOR THE AUTOMATIC INFINITE CAROUSEL
           $(this).bind('next', function () {
               gotoPage(currentPage + 1);
           });
       });  
   };

