var DEBUG_SCROLL = false

setupScrollable = function (scrollable) {
	if (scrollable.setup) return;
	if (DEBUG_SCROLL) {
		log('clientHeight', scrollable.clientHeight)
		log('scrollHeight', scrollable.scrollHeight)
	}
	setStyle(scrollable, {'overflow':'hidden'})
	
	
	/**
	 * the main vertical scroll function
	 * @param {Object} amount
	 * @param {Object} delay
	 */
	scrollable.auto_scroll = bind(function(amount, delay) {
		if (DEBUG_SCROLL) log("scroll",amount,delay)
		if (!this.isVerticalBounded()) return;
		try {
			if (this.scrollTimer) clearTimeout(this.scrollTimer)	//	stop timers if there are some
			
			new_pos = parseInt(this.scrollTop) + parseInt(amount)
			this.scrollTop = parseInt(new_pos)
			signal(this, 'onmanualscroll', {
				'amount': amount,
				'delay': delay
			})
			if (undefined != delay)
				this.scrollTimer = setTimeout(partial(this.auto_scroll, amount, delay), delay)
		} catch(e) {
			log("exception in scroll", e)
		}
	}, scrollable)
	scrollable.scroll = bind(function(amount, delay) {
		if (DEBUG_SCROLL) log("scroll",amount,delay)
		if (!this.isVerticalBounded()) return;
		try {
			if (this.scrollTimer) clearTimeout(this.scrollTimer)	//	stop timers if there are some
			new_pos = parseInt(this.scrollTop) + parseInt(amount) * 10
			Traverse(this, {scope:'scroll',transition:MochiKit.Visual.Transitions.linear,queue:'parallel',position:'end',
				duration:.35,
				'attrs': {
					'scrollTop': new_pos
				}
			})
			
			//this.scrollTop = parseInt(new_pos)
			
			signal(this, 'onmanualscroll', {
				'amount': amount,
				'delay': delay
			})
		} catch(e) {
			log("exception in scroll", e)
		}
	}, scrollable)
	scrollable.stopScroll = bind(function() {
		if (this.scrollTimer) clearTimeout(this.scrollTimer)
	}, scrollable)
	scrollable.scrollDown = bind(function(delay) {
		this.scroll(delay)
	}, scrollable)
	scrollable.scrollUp = bind(function(delay) {
		this.scroll(delay, true)
	}, scrollable)
	scrollable.scrollTo = bind(function(new_pos) {
		if (this.scrollTimer) clearTimeout(this.scrollTimer)	//	stop timers if there are some
		this.scrollTop = parseInt(new_pos)
	}, scrollable)
	scrollable.isVerticalBounded = bind(function(){
		return this.clientHeight < this.scrollHeight
	}, scrollable)
	scrollable.autoStop = bind(function(delay) {
		this.autoStopTimer = setTimeout(bind(function() {
			this.stopScroll()
			clearTimeout(this.autoStopTimer)
		}, scrollable), delay)
	}, scrollable)

	scrollable.setup = true
}

/**
 * initiates the scrollable target
 */
setup_scrollable_target = function(target){
	setupScrollable(target)
	var values = {
		delay: 1,
		amount: 20,
		title: "",
		autoStop: 150
	}
	var scroll_attrs = getNodeAttribute(target, "da:scrollable")
	if (scroll_attrs) {
		params = scroll_attrs.split(';')
		for (i in params) {
			var param = params[i].split('=')
			values[param[0]] = param[1]
		}
	}
	//setNodeAttribute(target, 'title', 'use your mouse wheel to scroll')

	connect(target, 'onmousewheel', bind(partial(function(amount, delay, autoStop, ev){
		this.scroll((ev.mouse().wheel.y / 3) * amount, delay)
		this.autoStop(autoStop)
		ev.stop()
		ev.stopPropagation()
	}, values.amount, values.delay, values.autoStop), target))
}

/**
 * initiates all stuff that the scroller is able to scroll
 */
setup_scrollable_scroller = function (scroller) {
	var values = {
		delay: 20,
		title: ""
	}
	var scroll_attrs = getNodeAttribute(scroller, "da:scrollable")
	if (!scroll_attrs) scroll_attrs = getNodeAttribute(scroller, "title")

	if (scroll_attrs) {
		params = scroll_attrs.split(';')
		for (i in params) {
			var param = params[i].split('=')
			values[param[0]] = param[1]
		}
	}
	if (values.target != 'undefined') {
		//	setup target
		var target = $(values.target)
		setupScrollable(target)
		//	connect handler
		connect(scroller, 'onmousedown', bind(partial(function(amount, delay, ev){
			this.auto_scroll(amount, delay)
		}, values.amount, values.delay), target))
		connect(scroller, 'onmouseup', bind(function(ev){
			this.stopScroll()
		}, target))
		connect(scroller, 'onmouseout', bind(function(ev){
			this.stopScroll()
		}, target))
		setNodeAttribute(scroller, 'title', values.title)
	}
}
/**
 * boot the scrollers
 * we trigger controll over the title attribute of the scroller
 * parameters are seperated by ";" and values are applied by "="
 * @param target:<the id of the target element to be scrolled>
 * @param amount:+/-number of units
 * @param delay:ms of time between next scroll
 * @param title:"the title after successful setup"
 */
addLoadEvent(function() {
	forEach(getElementsByTagAndClassName(null, 'scrollable'), setup_scrollable_target)

	forEach(getElementsByTagAndClassName(null, 'scroller'), setup_scrollable_scroller)
})