Glider = Class.create();
Object.extend(Object.extend(Glider.prototype, Abstract.prototype), {
	initialize: function(wrapper, options){
		this.scrolling  = false;
		this.wrapper    = $(wrapper);
		this.scroller   = this.wrapper.down('div.scroller');
		this.sections   = this.wrapper.getElementsBySelector('.section');
		this.options    = Object.extend({ duration: 1.0, frequency: 3, repeat: false, items: 1 }, options || {});
		
		var elemWidth = 0;
		this.sections.each( function(section, index) {
			section._index = index;
			if(!Prototype.Browser.IE){	
				elemWidth += section.clientWidth;
			}else{
				elemWidth += section.offsetWidth;
			}
		});    
		
		this.sections.width = elemWidth;
		this.scroller.width = this.scroller.clientWidth;
		this.scroller.offSets = Position.cumulativeOffset($(this.scroller));
		
		this.events = {
			click: this.click.bind(this),
			next: this.next.bind(this),
			prev: this.previous.bind(this)
		};
		
		this.addObservers();
		this.highlightLinks((this.options.initialSection) ? this.options.initialSection._index : 0, true);

		if (this.options.initialSection) this.moveTo(this.options.initialSection, this.scroller, { duration:this.options.duration });
		else this.moveTo(this.sections[0], this.scroller, { duration: this.options.duration });

		if (this.options.autoGlide) this.start();
	},
	
	addObservers: function() {
		var controls = this.wrapper.getElementsBySelector('div.controls a');
		controls.invoke('observe', 'click', this.events.click);
		
		this.nextLinks = this.wrapper.up().getElementsBySelector('.'+this.wrapper.id+'_next');
		this.nextLinks.invoke('observe', 'click', this.events.next);
		this.prevLinks = this.wrapper.up().getElementsBySelector('.'+this.wrapper.id+'_prev');
		this.prevLinks.invoke('observe', 'click', this.events.prev);
	},
	
	highlightLinks : function(index, first){
		if (this.noScrolled) return;
		if (first && (this.sections.length < 1 || this.sections.width < this.scroller.width)) {
			this.hideLinks('both');
			this.noScrolled = true;
		}
		else if (this.options.repeat) {
			this.hideLinks();
			this.noScrolled = true;
		}
		else if (index == 0) this.hideLinks('prev');
		else if (index > this.sections.length-this.options.items) this.hideLinks('next');
		else this.hideLinks();
	},
	
	hideLinks : function(direction) {
		switch (direction) {
			case 'both' : {
				this.nextLinks.invoke('removeClassName', 'active').invoke('addClassName', 'inactive');
				this.prevLinks.invoke('removeClassName', 'active').invoke('addClassName', 'inactive');
			}
			break;
			case 'next' : {
				this.nextLinks.invoke('removeClassName', 'active').invoke('addClassName', 'inactive');
				this.prevLinks.invoke('removeClassName', 'inactive').invoke('addClassName', 'active');
			}
			break;
			case 'prev' : {
				this.nextLinks.invoke('removeClassName', 'inactive').invoke('addClassName', 'active');
				this.prevLinks.invoke('removeClassName', 'active').invoke('addClassName', 'inactive');
			}
			break;
			default : {
				this.nextLinks.invoke('removeClassName', 'inactive').invoke('addClassName', 'active');
				this.prevLinks.invoke('removeClassName', 'inactive').invoke('addClassName', 'active');
			}
		}
	},

	click: function(event) {
		this.stop();
		var element = Event.findElement(event, 'a');
		if (this.scrolling) this.scrolling.cancel();
		
		this.moveTo(element.href.split("#")[1], this.scroller, { duration:this.options.duration });     
		Event.stop(event);
	},

	moveTo: function(element, container, options){
		this.current = $(element);
		
		var currentIndex = this.current._index;
		
		Position.prepare();
		var containerOffset = Position.cumulativeOffset(container),
		elementOffset = Position.cumulativeOffset($(element));
		
		this.scrolling 	= new Effect.SmoothScroll(container, {duration:options.duration, x:(elementOffset[0]-containerOffset[0]), y:(elementOffset[1]-containerOffset[1])});
		return false;
	},
		
	next: function(event){
		if (event) Event.stop(event);
		var nextIndex = this.current._index + this.options.items, currentOffSets = Position.cumulativeOffset($(this.current));
		if (nextIndex > this.sections.length || (this.scroller.width > this.sections.width - currentOffSets[0] + this.scroller.offSets[0])) {		
			if (!this.options.repeat) return;
			else nextIndex = 0;

		}
		else if (this.current._index < this.sections.length-1 && this.current._index >= this.sections.length - 1 - this.options.items) {
			var correct = false, nextIndex = this.current._index+1, d=this.sections[nextIndex].clientWidth;
			while (!correct) {
				if (this.scroller.width > this.sections.width - currentOffSets[0] + this.scroller.offSets[0] - d) {
					correct = true;
				}
				else {
					d+=this.sections[++nextIndex].clientWidth;
				}
			}
			/*nextIndex = this.sections.length - 1;*/
		}
		/*if (nextIndex >= this.sections.length || (this.scroller.width > this.sections.width - currentOffSets[0] + this.scroller.offSets[0])) {
			if (!this.options.repeat) return;
			else nextIndex = 0;
		}*/
		
		this.moveTo(this.sections[nextIndex], this.scroller, { duration: this.options.duration });
		
		this.highlightLinks(nextIndex);
	},
	
	previous: function(event){
		if (event) Event.stop(event);
		var prevIndex = (this.current._index < this.options.items && this.current._index>0) ? 0 : this.current._index - this.options.items;
		if (prevIndex < 0) {
				if (!this.options.repeat) return;
				else prevIndex = this.sections.length - 1;
		}
		
		this.moveTo(this.sections[prevIndex], this.scroller, { duration: this.options.duration });

		this.highlightLinks(prevIndex);
	},

	stop: function(){
		clearTimeout(this.timer);
	},
	
	start: function(){
		this.periodicallyUpdate();
	},
		
	periodicallyUpdate: function(){ 
		if (this.timer != null) {
			clearTimeout(this.timer);
			this.next();
		}
		this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency*1000);
	}

});

Effect.SmoothScroll = Class.create();
Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'absolute'
    } , arguments[1] || {}  );
    this.start(options);
  },
  setup: function() {
    if (this.options.continuous && !this.element._ext ) {
      this.element.cleanWhitespace();
      this.element._ext=true;
      this.element.appendChild(this.element.firstChild);
    }
   
    this.originalLeft=this.element.scrollLeft;
    this.originalTop=this.element.scrollTop;
   
    if(this.options.mode == 'absolute') {
      this.options.x -= this.originalLeft;
      this.options.y -= this.originalTop;
    }
  },
  update: function(position) {
    this.element.scrollLeft = Math.floor(this.options.x * position + this.originalLeft);
    this.element.scrollTop  = Math.floor(this.options.y * position + this.originalTop);
  }
});
