var ThumbScroller = new Class({
	Extends: Fx.Scroll,

	scrollOptions: {
		thumbs: '.thum',
		axis: 'x',
		thumbContainer: null,
		nav: {
			next: '#scrollNav .next',
			previous: '#scrollNav .previous'
		},
        startIndex: 0
    },

    initialize: function(element, scrollOptions) {
		this.parent(element, $merge(this.scrollOptions, scrollOptions));
        this.element.setStyle('overflow','hidden');
		this.computeDimensions();
        this.initNav();
		this.element.store('thumbscroller', this);
        this.toIndex(this.options.startIndex);
        this.lastScroll = null;
        return this;
	},

    computeDimensions: function() {
        this.thumbs = this.element.getElements(this.options.thumbs);
        this.setParentSize();
		this.positions = this.getLocations();
        return this;
    },

    isAtEnd: function(range) {
		range = range || this.getRange();
        return (range[range.length-1].index == this.thumbs.length-1 && range[range.length-1].type != 'partial');
	},
	isAtStart: function(range) {
		range = range || this.getRange()
		return (range[0].index == 0 && range[0].type != 'partial')
	},

	getLocations: function() {
		return this.thumbs.map(function(aThumb) {
			var tSize = aThumb.getComputedSize()[this.getDir('total')];
			var tStart = aThumb.getPosition(aThumb.getParent())[this.getDir('xy')];
			return {
				size: tSize,
				start: tStart,
				end: tSize + tStart
			}
		}, this);
	},

	initNav: function() {
		$$(this.options.nav.next).addEvent('click', this.toNextScreen.bind(this));
		$$(this.options.nav.previous).addEvent('click', this.toPreviousScreen.bind(this));
		$$(this.options.nav.start).addEvent('click', this.toStart.bind(this));
		$$(this.options.nav.end).addEvent('click', this.toEnd.bind(this));
	},

	getDir: function(type) {
		switch (type) {
			case 'total':
				if (this.options.axis == 'y') return 'totalHeight';
				return 'totalWidth';
			case 'dir':
				if (this.options.axis == 'y') return 'height';
				return 'width';
			case 'xy':
			default:
				if (this.options.axis == 'y') return 'y';
				return 'x';
		}
	},

	getStart: function(to) {
		if (this.options.axis == 'y')
			return [0,to];
		return [to,0];
	},

	getStartPx: function(index) {
		if (!index) return 0;
		return this.positions[index].start - (this.positions[index].start - this.positions[index-1].end);
	},

	setParentSize: function() {
		var parentElem = (this.options.thumbContainer) ? this.element.getElement(this.options.thumbContainer) : this.element.getElement(this.options.thumbs).getParent();
		var totalSize = 0;
		$each(this.thumbs, function(aThumb) {
			totalSize += aThumb.getComputedSize({styles: ['padding','border','margin']})[this.getDir('total')];
		},this);
		parentElem.setStyle(this.getDir('dir'), totalSize);
    },

	getRange: function(scrollStart) {
        scrollStart = scrollStart || this.element.getScroll()[this.getDir('xy')];
		var windowSize = this.element.getComputedSize({
			styles: ['padding']
		})[this.getDir('total')];
        var range = [];
        for (var x=0; x<this.positions.length; x++) {
			var tryRange = this.withinRange(this.positions[x], scrollStart, scrollStart + windowSize);
            if (tryRange) {
				range.push($merge(tryRange, {index: x}));
				if (tryRange.where == 'end') {
                    break;
                }
			}
		}
        return range;
	},

	withinRange: function(pos, viewStart, viewEnd) {
        if (pos.end > viewStart && pos.end <= viewEnd) {
			if (pos.start >= viewStart) {
				return {type: 'full'}
			} else {
				return {type: 'partial', where: 'start'};
			}
		} else if (pos.start >= viewStart && pos.start < viewEnd) {
			return {type: 'partial', where: 'end'};
		} else if (pos.start < viewStart && pos.end > viewEnd) {
			return {type: 'full'};
		}
		return false;
	},

	toNextScreen: function() {
		var range = this.getRange();
        if (range.getLast().type == 'partial' && range.length > 1) {
			this.start.run(this.getStart(this.getStartPx(range.getLast().index)), this);
		} else if ($(this.thumbs[range.getLast().index + 1])) {
			this.start.run(this.getStart(this.getStartPx(range.getLast().index+1)), this);
		} else {
			this.toEnd();
		}
        this.lastScroll = "next";
    },

	toPreviousScreen: function() {
		var range = this.getRange();
		var index = (range[0].type == 'partial' && range.length > 1) ? range[0].index : range[0].index - 1;
		if (!this.positions[index]) {
			this.toStart();
			return;
		}
		var startPos = this.positions[index].end - this.element.getComputedSize({styles: ['padding']})[this.getDir('total')];
		var pRange = this.getRange(startPos);
		var newIndex = (pRange[0].type=="partial" && pRange.length > 1) ? pRange[0].index+1 : pRange[0].index;
		this.start.run(this.getStart(this.getStartPx(newIndex)), this);
        this.lastScroll = "previous";
    },

	toIndex: function(index) {
		this.start.run(this.getStart(this.getStartPx(index)), this);
	},

	toStart: function() {
		if (this.options.axis == 'y') this.toTop();
		else this.toLeft();
	},

	toEnd: function() {
		if (this.options.axis == 'y') this.toBottom();
		else this.toRight();
	}

});

