/**
 * Class for handling scrollable advertisments
 */
Scroller = new Class({
	/**
	 * Constructor
	 * @param {Object} content The element that should be scrolled (could be passed by reference or by id)
	 * @param {Object} options
	 */
	initialize: function(content, options) {
		this.options = options;
	
		this.content = $(content);
		this.content.setStyle('position', 'relative');
		this.isScrolling = false;
		
		this.scrollHandler();
		
		this.position = this.savePosition = 0;
		
		// checks for scrolling changes every 200ms
		setInterval(this.run.bind(this), 200);
		
		// handles window scrolling event
		window.addEvent('scroll', this.scrollHandler.bind(this));
	},
	
	/**
	 * Handles window scrolling event
	 */
	scrollHandler: function() {
		// setup the new position and time when the scroll took place
		this.position = window.getScroll().y;
		this.time = new Date().getTime();
		
		// check wheather the bottom of the scrolling object is visible or not
		if (this.content.getSize().y + this.content.getPosition().y > window.getSize().y + window.getScroll().y) {
			this.bottomVisible = false;
		} else {
			this.bottomVisible = true;
		}
		
		// check wheather the user is scrolling up or down and adjust the speed accordingly
		if (this.position < this.savePosition) {
			this.scrollType = 1; // scrolling up
			this.speed = this.options.upSpeed;
		} else {
			this.scrollType = 2; // scrolling down
			this.speed = this.options.downSpeed;
		}
	},
	
	/**
	 * Update object when a scroll effect ended
	 */
	scrollStopped: function() {
		this.isScrolling = false;
	},
	
	/**
	 * Checks for context and starts the scrolling effects
	 */
	run: function() {
		if (this.scrollType == 2) {
			// if the user is scrolling down and the bottom is not visible, don't start the scrolling effect
			if (!this.bottomVisible) return;
	
			if (	(this.isScrolling && this.savePosition != this.position) || 
					(new Date().getTime() - this.time >= (this.options.delay * 1000) && !this.isScrolling) && this.savePosition != this.position) {
				// the scroll should start only if the bottom was visible for <<delay>> seconds or
				// if the window scroll has changed while the effect was taking place
				this.doScroll();
			}
		} else if (this.scrollType == 1) {
			// scrolling up effect is started immediatly
			if (this.savePosition != this.position) {
				this.doScroll();
			}
		}
	},
	
	/**
	 * Configures and starts the actual scrolling effect
	 */
	doScroll: function() {
		if (this.fx) this.fx.cancel();
		this.isScrolling = true;
		
		this.fx = new Fx.Tween(this.content, {duration: Math.abs(this.position - this.content.getStyle('top').toInt()) * this.speed, fps: 100});
		this.fx.addEvent('complete', this.scrollStopped.bind(this));
		this.savePosition = this.position;
		this.fx.start('top', this.position);
	}
});

/**
 * Helper code.
 * After the all elements are loaded, it automatically applies scrolling effects to
 * all elements that have <<scrollable>> class.
 */
window.addEvent('load', function() {
	$each($$(".scrollable"), function(item) {
		new Scroller(item, {
			delay: 3, // in seconds
			downSpeed: 15,  // double values are accepted (it represents the number of ms used to scroll 1px)
			upSpeed: 14  // double values are accepted (it represents the number of ms used to scroll 1px)
		});
	});
});


