if (!document.trace) {
	this.trace = function(output) {
		//if (console.log && output) console.log(output);
	}
}

/**
 * Scroll Pane (fixed horizontal)
 * @uses mootools-release-1.11.js
 */
 
var ScrollPane = new Class({
	
	initialize : function(controller) {
		trace('ScrollPane.initialize()');
		
		this.scrollParent = {};
		this.scrollContent = {};
		
		this.parentWidth = 0;
		this.contentWidth = 0;
		
		this.numItems = 0;
		this.resolution = 0;
		this.pageAmount = 0;
		
		this.currentX = 0;
		this.targetX = 0;
		this.invalidPosition = false;
		this.positionLoop = 0;
		
		this.currentSize = 2000;
		this.targetSize = 0;
		this.invalidSize = false;
		this.sizeLoop = 0;
		
		this.dampening = 1;
		this.quantizeWhenComplete = false;
		
		this.registered = false;
		
	},
	
	
	registerView : function(myDocElement) {
		trace('ScrollPane.registerView()');
		
		if (!myDocElement) return;
		
		// register document elements...
		
		this.scrollParent = myDocElement;
		this.scrollContent = this.getChildrenByClass(myDocElement, 'content')[0];
		
		// apply default styles to elements...
		
		this.scrollParent.setStyles('overflow: hidden; overflow-x: hidden; overflow-y: hidden;');
		this.scrollContent.setStyle('left', '0px');
		
		// define a fixed resolution since this is a fixed width item renderer...
		
		var item = this.getChildrenByClass(this.scrollContent, 'item')[0];
		this.resolution = this.getWidth(item);
		this.resolution += item.getStyle('margin-left').toInt() + item.getStyle('margin-right').toInt();
		this.resolution += item.getStyle('padding-left').toInt() + item.getStyle('padding-right').toInt();
		
		// set the scroll content width based on fixed resolution and item count
		
		this.numItems = this.getChildrenByClass(this.scrollContent, 'item').length;
		this.scrollContent.setStyle('width', this.resolution * this.numItems + 'px');
		this.parentWidth = this.getWidth(this.scrollParent);
		this.contentWidth = this.getWidth(this.scrollContent);
		this.pageAmount = this.parentWidth / (this.contentWidth - this.parentWidth);		
		
		//
		
		this.registered = true;
	},
	
	
	getWidth : function(element) {
		if (!element) return -1;
		var w = element.getSize().size.x;		
		return w;
	},
	
	
	scrollByPage : function(pages) {
		trace('ScrollPane.scrollByPage(' + pages + ')');
		
		if (!this.registered) return;
		var newAmountX = (-this.getScrollPosX() + this.parentWidth*pages)/(this.contentWidth - this.parentWidth);
		this.setScrollAmountX(newAmountX, true);
	},
	
	
	getScrollAmountX : function() {
		if (!this.registered) return 0;
		return -(this.getScrollPosX() / (this.contentWidth));
	},
	
	
	setScrollAmountX : function(amount, quantize) {
		
		if (!this.registered) return;
		
		if (amount < 0) amount = 0;
		if (amount > 1) amount = 1;
		
		this.currentX = parseInt(this.scrollContent.getStyle('left'));
		
		var targetX = -(this.contentWidth - this.parentWidth) * amount;
		
		if (quantize) this.quantizeWhenComplete = true;
		else this.quantizeWhenComplete = false;
		
		this.targetX = Math.round(targetX);
		
		if (parseInt(this.scrollContent.getStyle('left')) != this.newX) { 
			this.dampening = 0.30;
			this.invalidatePosition();
		}
	},
	
	
	quantize : function() {
		var delayQuantize = this.applyQuantize.delay(100, this);
	},
	
	
	applyQuantize : function() {
		var x = parseInt(this.scrollContent.getStyle('left'));
		var roundX = Math.round(x / this.resolution);
		this.targetX = Math.round(roundX * this.resolution);
		
		this.dampening = 0.10;
		this.invalidatePosition();
	},
	
	
	invalidatePosition : function() {
		if (!this.invalidPosition) {
			this.invalidPosition = true;
			this.positionLoop = this.updatePosition.periodical(10, this);
		}
	},
	
	
	updatePosition : function() {
		
		if (Math.abs(this.targetX - this.currentX) <= 0.01) { 
			this.currentX = this.targetX;
			this.setScrollPosX(this.targetX);
			this.validatePosition();
		} else {
			this.currentX += (this.targetX - this.currentX) * this.dampening;
			this.setScrollPosX(this.currentX);
		}
		
		//
		
		this.scrollParent.fireEvent('onScrollX');
	},
	
	
	validatePosition : function() {
		
		this.invalidPosition = false;
		this.positionLoop = $clear(this.positionLoop);
		
		if (this.quantizeWhenComplete) {
			this.quantizeWhenComplete = false;
			this.quantize();
		}
	},
	
	
	invalidateSize : function() {
			
		if (!this.invalidSize) {
			this.invalidSize = true;
			this.sizeLoop = this.updateSize.periodical(10, this);
		}
	},
	
	
	updateSize : function() {
	
		if (Math.abs(this.targetSize - this.currentSize) <= 0.01) {
			this.currentSize = this.targetSize;
			this.setScrollSize(this.targetSize);
			this.validateSize();
		} else {
			this.currentSize += (this.targetSize - this.currentSize) * this.dampening;
			this.setScrollSize(this.currentSize);
		}
	
		this.parentWidth = this.getWidth(this.scrollParent);
		this.contentWidth = this.getWidth(this.scrollContent);
		this.pageAmount = this.parentWidth / (this.contentWidth - this.parentWidth);		
		
		// 
		
		this.scrollParent.fireEvent('onScrollResize');
	},
	
	
	validateSize : function() {
		this.invalidSize = false;
		this.sizeLoop = $clear(this.sizeLoop);
		this.quantize();
	},
	
	
	getScrollPosX : function() {
		if (!this.registered) return 0;
		return parseInt(this.scrollContent.getStyle('left'));
	},
	
	
	setScrollPosX : function(position) {
		if (!this.registered) return;
		this.scrollContent.setStyle('left', Math.round(position) + 'px');
	},
	
	
	getScrollSize : function() {
		if (!this.registered) return 0;
		return parseInt(this.scrollContent.getStyle('width'));
	},
	
	
	setScrollSize : function(width) {
		if (!this.registered) return;
		this.scrollContent.setStyle('width', Math.round(width) + 'px');
	},
	
	
	filterChildren : function(filterClass) {
		trace('ScrollPane.filterChildren(' + filterClass + ')');
		
		var items = this.getChildrenByClass(this.scrollContent, 'item');
		this.numItems = 0;
		
		for (var i = 0; i < items.length; ++i) {
			
			var item = items[i];
			
			if (filterClass && !item.hasClass(filterClass)) {
				item.setStyle('position', 'absolute');
				item.setStyle('left', '-1000px');
			} else {
				item.setStyles('');
				this.numItems++;
			}
		}
		
		this.currentSize = this.getScrollSize();
		this.targetSize = this.numItems * this.resolution;
		
		this.invalidateSize();
	},
	
	
	/**
	 * @return	The children of an element with a specified class.
	 */
	getChildrenByClass : function (docElement, className) {
	
		if (!docElement || !className) return;
		
		var result = new Array();
		var children = docElement.getChildren();
		
		for (var i = 0; i < children.length; ++i) {
			if (children[i].hasClass(className)) result.push(children[i]);
		}
		
		return result;
	},
	
	
	toString : function() {
		return "[ScrollPane]";
	}
		
});
