// pluit-carousel.js v1.0.0

// Copyright (c) 2010 Herryanto Siatono (http://www.pluitsolutions.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// IMPORTANT:
// MODIFICATION OF THE ORIGINAL CAROUSEL-PLUIT TO ALLOW FADE TRANSITION
// AND TO STOP/START THE CAROUSEL ONMOUSEOVER/ONMOUSEOUT

var Pluit = {};

Pluit.Carousel = Class.create({
	  initialize: function() {
	    var elements = $A(arguments);
	    var options = {};
	    if (typeof elements.last() === 'object') {
	      options = elements.pop();
	    }
	    
	    elements.each(function(element) {
	      new Pluit.Carousel.Element(element, options);
	    });
	  }
	});

	Pluit.Carousel.Element = Class.create({
	  initialize: function(elCarousel, options) {
	    this.initOptions(options);
	    this.initElements(elCarousel);
	    this.initViewport();
	    this.initNavigation();
	    if (this.options.autoPlay) {
	      this.play();
	    }
	  },

	  initOptions: function(options) {
	    this.options = {
	      circular: false,
	      hideAutoNav: false,
	      animDuration: 0.5,
	      autoPlay: false,
	      slideDuration: 3,
	      viewportClassName: 'viewport',
	      navClassName: 'nav',
	      prevClassName: 'prev',
	      nextClassName: 'next',
	      pagesClassName: 'pages',
	      pageClassNamePrefix: 'page-',
	      activeClassName: 'active',
	      holdtime: 15,
	    };

	    Object.extend(this.options, options || { });
	  },

	  initElements: function(elCarousel) {
	    if (Object.isString(elCarousel)) {
	      if (elCarousel.startsWith('#')) {
	        elCarousel = elCarousel.substring(1);
	      }
	    }
	    
	    this.elCarousel = $(elCarousel);
	    this.elViewport = this.elCarousel.down('.' + this.options.viewportClassName);
	    this.elSlidesPanel = this.elViewport.firstDescendant();
	    this.elSlides = this.elSlidesPanel.childElements();

	    this.elNav = this.elCarousel.down('.' + this.options.navClassName);
	    this.maxPageNo = this.elSlides.length;

	    this.prevPageNo = this.curPageNo = 1;
	  },

	  initViewport: function() {
	    // Resize viewport
	    if (this.elSlides.length === 0) {
	      return;
	    }

	    this.viewportDimension = this.getViewportDimension();

	    this.elCarousel.setStyle({
	      width: this.viewportDimension[0] + 'px'
	    });

	    this.elViewport.setStyle({
	      width: this.viewportDimension[0] + 'px',
	      height: this.viewportDimension[1] + 'px'
	    });

	    //this.elViewport.observe('click', this.onViewportClick.bindAsEventListener(this));
	    this.elViewport.observe('mouseover', this.onViewportMouseOver.bindAsEventListener(this));
	    this.elViewport.observe('mouseout', this.onViewportMouseOut.bindAsEventListener(this));
	    
	    
	  },

	  initNavigation: function() {
	    this.elNav = this.elCarousel.down('.nav');
	    if ((!this.elNav) && (!this.options.hideAutoNav)) {
	      this.elNav = this.buildNavigation();
	      this.elNav = $(this.elNav);
	    }

	    if (!this.elNav) {
	      return;
	    }

	    this.elNav.observe('click', this.onNavClick.bindAsEventListener(this));
	  },

	  buildNavigation: function() {
	    var elNav = document.createElement('ul');
	    elNav.className = 'nav';

	    var navHTML = '';

	    navHTML += '<li class="' + this.options.prevClassName + '"><a href="#">Prev</a></li>';

	    if (this.maxPageNo > 0) {
	      navHTML += '<li class="' + this.options.pagesClassName + '"><ul>';
	      for (var i=0; i<this.maxPageNo; i++) {
	        navHTML += '<li class="';
	        if (i === 0) {
	          navHTML += this.options.activeClassName + ' ';
	        }
	        navHTML += this.options.pageClassNamePrefix + (i + 1) + '"><a href="#">' + (i + 1) + '</a></li>';
	      }
	      navHTML += '</ul></li>';
	    }

	    navHTML += '<li class="' + this.options.nextClassName + '"><a href="#">Next</a></li>';

	    elNav.innerHTML = navHTML;
	    this.elCarousel.insert(elNav);

	    return elNav;
	  },

	  getViewportDimension: function() {
	    // Get first page width instead
	    var firstPage = this.elSlides[0];
	    return [firstPage.getWidth(), firstPage.getHeight()];
	  },
	    
	  // Event Listeners
	  onNavClick: function(e) {
	    clearTimeout(this.myTimer);
	    var navItem = e.findElement('li');
	    if (!navItem) {
	      return;
	    }
	    var className = navItem.className;
	    if (className === this.options.prevClassName) {
	      this.movePrevious();
	    } else if (className === this.options.nextClassName) {
	      this.moveNext();
	    } else if (className.match(this.options.pageClassNamePrefix)) {
	      var pageNo = parseInt(className.split('-')[1], 10);
	      this.movePage(pageNo);
	    }
	    e.preventDefault(); 
	  },
	  


	    onViewportMouseOver: function(e) {
	    clearTimeout(this.myTimer);
	  },
	    onViewportMouseOut: function(e) {
	    clearTimeout(this.myTimer);
	    this.play();
	  },

	  // Helper Methods
	  moveNext: function() {
	    this.movePage(this.curPageNo + 1);
	  },

	  movePrevious: function() {
	    this.movePage(this.curPageNo -1);
	  },

	  movePage: function(pageNo) {
	    // Ignore when carousel is in animated state
	    if (this.onTheMove) {
	      return;
	    }

	    // No changes, do nothing
	    if (pageNo === this.curPageNo) {
	      return;
	    }

	    // Check for valid pageNo, reset pageNo if required
	    pageNo = this.checkPageNo(pageNo, this.curPageNo);

	    // Check distance
	    var distance = this.getMoveDistance(pageNo, this.curPageNo);

	    this.onTheMove = true;

	    this.activatePageNav(pageNo);

	    if (this.options.effect === 'fade') {
	      var duration = this.options.animDuration / 2;
	      new Effect.Fade(this.elSlidesPanel, {
	        duration: duration,
	        afterFinish: function() {
	          new Effect.Move(this.elSlidesPanel, {
	            x: distance,
	            duration: 0,
	            afterFinish: function() {
	              this.onTheMove = false;
	              new Effect.Appear(this.elSlidesPanel, {
	                duration: duration,
	              });
	            }.bind(this)
	          });
	        }.bind(this)
	      });
	    } else {
	      new Effect.Move(this.elSlidesPanel, {
	        x: distance,
	        duration: this.options.animDuration,
	        afterFinish: function() {
	          this.onTheMove = false;
	        }.bind(this)
	      });
	    }

	    this.curPageNo = pageNo;
	  },

	  play: function() {
	    this.myTimer = setTimeout(function() {
	        if (this.options.autoPlay) {
	            this.moveNext();
	            this.play();
	        }
	    }.bind(this), this.options.slideDuration * 1000);
	  },

	  isMovePrevious: function(pageNo, curPageNo) {
	    if (pageNo < curPageNo) {
	      return true;
	    }
	  },

	  getMoveDistance: function(pageNo, curPageNo) {
	    var distance = 0;

	    if (pageNo === curPageNo) {
	      return distance;
	    }

	    var isPrevious = this.isMovePrevious(pageNo, curPageNo);
	    if (isPrevious) {
	      // Move Previous
	      while (pageNo < curPageNo) {
	        distance += this.elSlides[pageNo - 1].getWidth();
	        pageNo += 1;
	      }

	      return distance;
	    } else {
	      // Move Next
	      while (pageNo > curPageNo) {
	        distance += this.elSlides[pageNo - 2].getWidth();
	        pageNo -= 1;
	      }

	      return -distance;
	    }
	  },

	  activatePageNav: function(pageNo) {
	    if (!this.elNav) {
	      return;
	    }

	    var elNavItem = this.elNav.down('.page-' + pageNo);
	    var elCurNavItem = this.elNav.down('.page-' + this.curPageNo);

	    if (!elNavItem && !elCurNavItem) {
	      return;
	    }

	    elCurNavItem.removeClassName(this.options.activeClassName);
	    elNavItem.addClassName(this.options.activeClassName);
	  },

	  checkPageNo: function(pageNo, curPageNo) {
	    var isPrevious = this.isMovePrevious(pageNo, curPageNo);

	    if (isPrevious) {
	      if (pageNo < 1) {
	        if (this.options.circular) {
	          return this.maxPageNo;
	        } else {
	          return 1;
	        }
	      }
	    } else {
	      if (pageNo > this.maxPageNo) {
	        if (this.options.circular) {
	          return 1;
	        } else {
	          return this.maxPageNo;
	        }
	      }
	    }

	    return pageNo;
	  }
	});

	Object.extend(Pluit.Carousel, {
	  Version: '1.2.0',
	  
	  init: function() {
	    var cssRules = $A(arguments);
	    var options = null;

	    if (typeof cssRules.last() === 'object') {
	      options = cssRules.pop();
	    }

	    if (cssRules.length === 0) {
	      cssRules = ['.pluit-carousel'];
	    }

	    document.observe("dom:loaded", function() {
	      $A(cssRules).each(function(cssRule) {
	        $$(cssRule).each(function(carousel) {
	          new Pluit.Carousel(carousel, options);
	        }.bind(this));
	      });
	    });
	  }
	});
