var MaskedScroll = Class.create({
	slider: undefined, // mask container
	current: undefined, // currently selected element
	elements: [], // array of elements inside slider
	duration: .5, // how long should the effect take
	transition: undefined, // Effect.Transition for the effect
	viewSize: 1, // how many elements are visible at once
	distanceBeforeSlowDown: false, // number of pixels for the movement for a slowdown
	slowDownMultiplier: 1, // multiply duration by this number for a slow down if distanceBeforeSlowDown != false
	prevButton: undefined, // id of button to go back
	nextButton: undefined, // id of button to go forward
	
	initialize: function(slider, prev, next, options) {
	
		this.scroll_lock = false;
		
		this.slider = $(slider);
		this.current = this.slider.down();
		this.elements = this.slider.childElements();
		
		if (!options) options = {};
		this.duration = options.duration || .5;
		this.transition = options.transition || Effect.Transitions.sinoidal;
		this.viewSize = options.viewSize || false;
		this.distanceBeforeSlowDown = options.distanceBeforeSlowDown || false;
		this.slowDownMultiplier = options.slowDownMultiplier || 1.5;
		
		this.prevButton = $(prev);
		this.nextButton = $(next);						

		this.prevButton.observe('click', (function() { 
			var element = this.current.previous() || this.elements[this.elements.length - 1];
			if (this.viewSize && (this.getPos(element) > this.elements.length - this.viewSize)) {
				this.scrollElement((this.elements.length - this.viewSize > 0) ? this.elements.length - this.viewSize : 0);
				return;
			}
			this.scrollElement(element);			
		}).bind(this));
		this.nextButton.observe('click', (function() { 
			var element = this.current.next() || this.elements[0];
			if (this.viewSize && (this.getPos(element) > this.elements.length - this.viewSize)) {
				this.scrollElement(0);
				return;
			}
			this.scrollElement(element);
		}).bind(this));
	},
	scrollElement: function(element) {
		if (!isNaN(element)) element = this.elements[element];
		var xchange = this.current.viewportOffset()[0] - element.viewportOffset()[0];
		var ychange = this.current.viewportOffset()[1] - element.viewportOffset()[1];
		this.animate(xchange, ychange);
		this.current = element;
	},
	first: function() { this.scrollElement(0); },
	last: function() { 
		var pos = (this.viewSize) ? (this.elements.length - this.viewSize) : this.elements.length - 1;
		if (pos < 0) pos = 0;
		this.scrollElement(pos);
	},
	getPos: function(element) { return element.previousSiblings().length; },
	animate: function(xchange, ychange) {
		this.scroll_lock = true;
		var time_duration = (this.distanceBeforeSlowDown && (Math.abs(xchange) > this.distanceBeforeSlowDown || Math.abs(ychange) > this.distanceBeforeSlowDown)) ? (this.duration * this.slowDownMultiplier) : this.duration;
		new Effect.Move(this.slider, {
			x: xchange,
			y: ychange,
			duration: time_duration,  
			transition: this.transition,
			afterFinish: (function() { 
				this.scroll_lock = false;
			}).bind(this)
		});
	},
	updatePosition: function() {
		this.elements = this.slider.childElements();
		if (this.current) {
			if (this.current.viewportOffset()[0] != this.slider.up().viewportOffset()[0] || this.current.viewportOffset()[1] != this.slider.up().viewportOffset()[1] + 7) {
				this.elements.each((function(el) {
					if (el.viewportOffset()[0] == this.slider.up().viewportOffset()[0] && el.viewportOffset()[1] == this.slider.up().viewportOffset()[1] + 7) {
						this.current = el;
					}
				}).bind(this));
			}
		} else this.current = this.elements[0];
	}
});