

var Carousel = Class.create();
Carousel.prototype =
{
  // Constructor
  initialize: function(carouselElemID)
  {
    this.carouselElemID = carouselElemID;
    
    this.options = Object.extend
    (
	    {
	      numVisible:						4,
	      scrollInc:            3,
	      animParameters:      	{},
	      buttonStateHandler:  	null,
	      animHandler:         	null,
	      ajaxHandler:         	null,
	      initDoneHandler:     	null,
	      queue:               	"carousel",
	      size:                	0,
	      prevElementID:       	"prev-arrow",
	      nextElementID:       	"next-arrow",
	      ajaxParameters:      	null,
				orientation:				 	"horizontal", //ou vertical
	      url:                 	null,
	      imgNavID:							null
			}, arguments[1] || {}
		);

		this.initDone = false;
		this.animRunning = "none";
    this.requestIsRunning = false;
    this.w3c = document.getElementById ? true : false;
		this.iex = (navigator.appName == 'Microsoft Internet Explorer') ? true : false;
    
		// add afterFinish options to animParameters (store old function)
		this.animAfterFinish = this.options.animParameters.afterFinish;
		Object.extend
		(
			this.options.animParameters,
			{
				afterFinish:	this._animDone.bind(this),
				queue: 				{
												position:'end',
												scope: this.options.queue 
											}
			}
		);
	  
		// Event bindings
		this.prevScroll = this._prevScroll.bindAsEventListener(this);
		this.nextScroll = this._nextScroll.bindAsEventListener(this);
		this.onComplete = this._onComplete.bindAsEventListener(this);
		this.onFailure  = this._onFailure.bindAsEventListener(this);
		//added by spidou
		if (this.options.imgNavID != null)
		{
			this.prevRollOver = this._prevRollOver.bindAsEventListener(this);
			this.nextRollOver = this._nextRollOver.bindAsEventListener(this);
			this.prevAndNextRollOut = this._prevAndNextRollOut.bindAsEventListener(this);
		}

		Event.observe(this.options.prevElementID, "click", this.prevScroll);
		Event.observe(this.options.nextElementID, "click", this.nextScroll);
		//added by spidou
		if (this.options.imgNavID != null)
		{
			Event.observe(this.options.prevElementID, "mouseover", this.prevRollOver);
			Event.observe(this.options.nextElementID, "mouseover", this.nextRollOver);
			Event.observe(this.options.prevElementID, "mouseout", this.prevAndNextRollOut);
			Event.observe(this.options.nextElementID, "mouseout", this.prevAndNextRollOut);
		}
				
		// Get DOM UL element
		var carouselListClass = "carousel-list";
		this.carouselList = document.getElementsByClassName(carouselListClass, $(carouselElemID))[0]
		this.options.size =  $(this.carouselList.getElementsByTagName("li")).length;
		// Init data
		this._init();
  },
  
  // Destructor
 	destroy: function()
 	{
  	Event.stopObserving(this.options.prevElementID, "click", this.prevScroll);
  	Event.stopObserving(this.options.nextElementID, "click", this.nextScroll);
  	//added by spidou
  	if (this.options.imgNavID != null)
  	{
			Event.stopObserving(this.options.prevElementID, "mouseover", this.prevRollOver);
			Event.stopObserving(this.options.nextElementID, "mouseover", this.nextRollOver);
			Event.stopObserving(this.options.prevElementID, "mouseout", this.prevAndNextRollOut);
			Event.stopObserving(this.options.nextElementID, "mouseout", this.prevAndNextRollOut);
		}
	},
	
	scrollTo: function(newStart)
	{
		var old_inc = this.options.scrollInc;
		this.ignoreNoMoreImages = true;
		if(newStart > this.currentIndex)
		{
			this.options.scrollInc = newStart - this.currentIndex;
			this._nextScroll(this);
		}
		else
		{
			this.options.scrollInc = this.currentIndex - newStart;
			this._prevScroll(this);
		}
    this.options.scrollInc = old_inc;
	},
	
  /* "Private" functions */
  _init: function()
  {
    this.currentIndex = 0;
      
    // Ajax content
    if (this.options.url)
  	  this._request(this.currentIndex, this.options.numVisible);
	  // Static content
  	else
  	{
  	  this._getLiElementSize();
  		this._updateButtonStateHandler(this.options.prevElementID, false);
  		this._updateButtonStateHandler(this.options.nextElementID, this.options.size > this.options.numVisible);
  	}
  	
  	//added by Spidou
  	if (this.options.imgNavID != null)
  	{
  		element = document.getElementById(this.options.imgNavID);
  		//this.imgNavDefaultMarginTop = element.getStyle("marginTop");
  	}
  },
  
  //added by Spidou
  _prevRollOver: function(event)
  {
  	if (this.currentIndex > 0)
  	{
	  	element = document.getElementById(this.options.imgNavID);
	  	
	  	if (this.options.orientation == "horizontal")
	  	{
		  	h = element.getDimensions().height / 3;
		  	element.setStyle
		  	(
		  		{
					  marginTop: '-' + h + 'px'
					}
				);
			}
			else
			{
				w = element.getDimensions().width / 3;
		  	element.setStyle
		  	(
		  		{
					  marginLeft: '-' + w + 'px'
					}
				);
			}
		}
  },
  
  //added by Spidou
  _nextRollOver: function(event)
  {
  	if (this.currentIndex + this.options.scrollInc < this.options.size)
  	{
	  	element = document.getElementById(this.options.imgNavID);
	  	
	  	if (this.options.orientation == "horizontal")
	  	{
		  	h = element.getDimensions().height / 3;
		  	element.setStyle
		  	(
		  		{
					  marginTop: '-' + 2 * h + 'px'
					}
				);
			}
			else
			{
				w = element.getDimensions().width / 3;
		  	element.setStyle
		  	(
		  		{
					  marginLeft : '-' + 2 * w + 'px'
					}
				);
			}
		}
  },
  
  //added by Spidou
  _prevAndNextRollOut: function(event)
  {
  	element = document.getElementById(this.options.imgNavID);
  	
  	if (this.options.orientation == "horizontal")
  	{
	  	element.setStyle
	  	(
	  		{
				  marginTop: '0px'
				}
			);
		}
		else
		{
			element.setStyle
	  	(
	  		{
				  marginLeft: '0px'
				}
			);
		}
  },
  
  _prevScroll: function(event)
  {
    if (this.animRunning != "none" || this.currentIndex == 0)
      return;

    var inc = this.options.scrollInc;

    if (this.currentIndex - inc < 0)
      inc = this.currentIndex;

    this._scroll(inc)		  
	  return false;
  },
  
  _nextScroll: function(event)
  {    
    if (this.animRunning != "none")
      return false;
            
    // Check if there are enough elements in cache
    if (this.currentIndex + this.options.numVisible + this.options.scrollInc <= this.options.size)
      this._scroll(-this.options.scrollInc);
    else
    {
      // Compute how many are in the cache
      this.nbInCache = this.options.size - (this.currentIndex + this.options.numVisible);
      if (this.options.url && this.noMoreImages == false) 
		    this._request(this.currentIndex + this.options.numVisible + this.nbInCache, this.options.scrollInc - this.nbInCache);
	    else
	    {
	      if (this.nbInCache > 0)
          this._scroll(-this.nbInCache);
      }
	  }
	  return false;
  },
  
  _request: function(start, nb)
  {
    if (this.options.url && ! this.requestIsRunning)
    {
      this.requestIsRunning = true;
      
      if (this.options.ajaxHandler)
        this.options.ajaxHandler(this, "before");
      
      var params = "start=" + start + "&nb=" + nb;
      if (this.options.ajaxParameters != null)
        params += "&" + this.options.ajaxParameters
      
  		new Ajax.Request(this.options.url, {parameters: params, onComplete: this.onComplete, onFailure: this.onFailure});
		}
  },
  
  _onComplete: function(originalRequest)
  {
    this.requestIsRunning = false;
    this.carouselList.innerHTML += originalRequest.responseText;
    // Compute how many new elements we have
    var size = this.options.size;
    this.options.size = this.carouselList.getElementsByTagName("li").length;
    var inc = this.options.size - size;
    
		// First run, compute li size
		if (this.initDone == false)
		{
  		this._getLiElementSize()
  		this.currentIndex = 0;
  		this.initDone = true;
      if (this.options.initDoneHandler) 
        this.options.initDoneHandler(this);
         
  		// Update button states
		  this._updateButtonStateHandler(this.options.prevElementID, false);
		  this._updateButtonStateHandler(this.options.nextElementID, this.options.size == this.options.numVisible);
		  this.noMoreImages = this.options.size < this.options.numVisible
		}
		// Add images
		else
		{
		  if (!this.ignoreNoMoreImages)
		    this.noMoreImages = inc != this.options.scrollInc;
		  else
		    this.ignoreNoMoreImages = false;
		  // Add images
		  if (inc > 0)
		  {
        this._scroll(-inc, this.noMoreImages)
      }
      // No more images, disable next button
		  else
		  {
		    if (this.nbInCache >0)
          this._scroll(-this.nbInCache, true);
		    
		    this._updateButtonStateHandler(this.options.nextElementID, false);
	    }
		}
		if (this.options.ajaxHandler)
      this.options.ajaxHandler(this, "after");
  },
  
  _onFailure: function(originalRequest)
  {    
    this.requestIsRunning = false;
  },

  _animDone: function(event)
  {   
    if (this.options.animHandler)
      this.options.animHandler(this.carouselElemID, "after", this.animRunning);
     
    this.animRunning = "none";
    // Call animAfterFinish if exists
    if (this.animAfterFinish)
      this.animAfterFinish(event);
  },
  
  _updateButtonStateHandler: function(button, state)
  {
		if (this.options.buttonStateHandler) 
		    this.options.buttonStateHandler(button, state)
	},
  
  _scroll: function(delta, forceDisableNext)
  {
    this.animRunning = delta > 0 ? "prev" : "next";
    
    if (this.options.animHandler)
      this.options.animHandler(this.carouselElemID, "before", this.animRunning);

    test = this._getLiElementSize(); //added by Spidou (sinon ca marche pas !! )
    
		//vertical orientation
		if(this.options.orientation == "vertical")
		{
			new Effect.MoveBy(this.carouselList, delta * this.elementSize, 0, this.options.animParameters);
		}
		else
		{
			new Effect.MoveBy(this.carouselList, 0, delta * this.elementSize, this.options.animParameters);	
		} 
	
    this.currentIndex -= delta;
    this._updateButtonStateHandler(this.options.prevElementID, this.currentIndex != 0);
    
    if (this.options.url && this.noMoreImages == false)
      enable = true;
    else
      enable = (this.currentIndex + this.options.numVisible < this.options.size);
    this._updateButtonStateHandler(this.options.nextElementID, (forceDisableNext ? false : enable));
  },
  
  _getLiElementSize: function()
  {
    var li = $(this.carouselList.getElementsByTagName("li")[0]);
		//this.elementSize = li.getDimensions().width + parseFloat(li.getStyle("margin-left")) + parseFloat(li.getStyle("margin-right"));
		if(this.options.orientation == "vertical")
		{
			this.elementSize = li.getDimensions().height + parseFloat(li.getStyle("margin-top")) + parseFloat(li.getStyle("margin-bottom"));
		}
		else
		{
			this.elementSize = li.getDimensions().width + parseFloat(li.getStyle("margin-left")) + parseFloat(li.getStyle("margin-right"));
		}
  }
}

