// --------------------- ViewPort ----------------------

ViewPort = function(container, panel, panelH) {
	this.container = (typeof container == 'object') ? container : dom.getElementById(container);
	this.panel = (typeof panel == 'object') ? panel : dom.getElementById(panel);
	
	this.containerH = dom.getH(this.container);
	if (panelH) this.panelH = panelH;
	else this.panelH = dom.getH(this.panel);
	
	this.maxY = 0;
	this.minY = this.containerH - this.panelH;
	if (this.minY > this.maxY) this.minY = 0;
	
	this.currentY = 0;
}
ViewPort.prototype = new EventObject();


ViewPort.prototype.isScrollable = function() {
	return !(this.minY == this.maxY);
}
ViewPort.prototype.getRatio = function() {
	return (this.minY != 0) ? this.currentY / this.minY : 0;
}
ViewPort.prototype.setRatio = function(r) {
	r = (r < 0) ? 0 : (r > 1) ? 1 : r;
	this.currentY = Math.round(r * this.minY);
	dom.setProperties(this.panel, {y:this.currentY});
}

ViewPort.prototype.moveUp = function(amount) {
	this.currentY += amount;
	if (this.currentY > this.maxY) this.currentY = this.maxY;
	dom.setProperties(this.panel, {y:this.currentY});
	this.invokeEvent({
		type:'ratiochange',
		ratio: this.getRatio()
	});
}
ViewPort.prototype.moveDown = function(amount) {
	this.currentY -= amount;
	if (this.currentY < this.minY) this.currentY = this.minY;
	dom.setProperties(this.panel, {y:this.currentY});
	this.invokeEvent({
		type:'ratiochange',
		ratio: this.getRatio()
	});
}

//---------------------- Slider ---------------------------

Slider = function(knob, range) {
	this.knob = (typeof knob == 'string') ? dom.getElementById(knob) : knob;
	this.knob.sl = this;
	
	this.range = range;
	this.X = dom.getX(this.knob);
	this.minY = dom.getY(this.knob);
	this.maxY = this.minY + range;
	
	drag.enable(this.knob);
	this.knob.dragBoundary = [this.minY, this.X, this.maxY, this.X];
	this.knob.ondragmove = Slider.dragmoveFunc;
	this.host = this.knob.parentNode;
	this.host.sl = this;
	this.host.onclick = Slider.clickFunc;
}
Slider.prototype = new EventObject();

Slider.prototype.dragmoveHandler = function() {
	this.invokeEvent({
		type: 'ratiochange',
		ratio: (dom.getY(this.knob)-this.minY) / this.range
	});
}
Slider.prototype.clickHandler = function(e) {
	if (ua.ie) e = event;
	
	var knobY = dom.getY(this.knob);
	var eventY = e.clientY - dom.getPageY(this.host);

	var dir = false;
	var db = this.knob.dragBoundary;
	if (eventY > db[0] && eventY < knobY) dir = 'up';
	else if (eventY < db[2] + dom.getH(this.knob) && eventY > knobY) dir ='down';
	
	if (dir) this.invokeEvent({type:'sliderclick',direction:dir});
}
Slider.prototype.setRatio = function(r) {
	r = (r < 0) ? 0 : (r > 1) ? 1 : r;
	var y = Math.round(this.minY + r * this.range);
	dom.setProperties(this.knob, {y:y});
}

// Eventhandlers
Slider.dragmoveFunc = function() { this.sl.dragmoveHandler(); }
Slider.clickFunc = function(e) { this.sl.clickHandler(e); }

//---------------------- ScrollPort -----------------------

/*
conf = {
	viewPort
	buttonUpId
	buttonDownId
	slider
	scrollstep
	wheelstep
	interval
}
*/	

ScrollPort = function(conf) {
	if (!conf.pixelspersecond) conf.pixelspersecond = 120;
	if (!conf.wheelstep) conf.wheelstep = 20;
	if (!conf.interval) conf.interval = 20;
	
	this.conf = conf;

	this.viewPort = conf.viewPort;
	this.viewPort.sp = this;
	this.viewPort.addEventHandler('endreached', ScrollPort.stopScroll);
	//this.viewPort.addEventHandler('move', *******);
	
	if (conf.buttonUp) {
		this.up = (typeof conf.buttonUp == 'object') ? conf.buttonUp : dom.getElementById(conf.buttonUp);
		this.up.sp = this;
		if (conf.sethoverhandlers) {
			this.up.onmouseover = ScrollPort.buttonUpMousedownHandler;
			this.up.onmouseout = ScrollPort.stopScroll;
		}
		else {
			this.up.onmousedown = ScrollPort.buttonUpMousedownHandler;
			this.up.onmouseup = this.up.onmouseout = ScrollPort.stopScroll;
		}
	}
	if (conf.buttonDown) {
		this.down = (typeof conf.buttonDown == 'object') ? conf.buttonDown : dom.getElementById(conf.buttonDown);
		this.down.sp = this;
		if (conf.sethoverhandlers) {
			this.down.onmouseover = ScrollPort.buttonDownMousedownHandler;
			this.down.onmouseout = ScrollPort.stopScroll;
		}
		else {
			this.down.onmousedown = ScrollPort.buttonDownMousedownHandler;
			this.down.onmouseup = this.down.onmouseout = ScrollPort.stopScroll;
		}
	}

	if (conf.slider) {
		this.slider = conf.slider;
		this.slider.sp = this;
		
		this.viewPort.addEventHandler('ratiochange', function(e) {
			this.sp.slider.setRatio(e.ratio);
		});
		
		this.slider.addEventHandler('ratiochange', function(e) {
			this.sp.viewPort.setRatio(e.ratio);
		});
		
		this.slider.addEventHandler('sliderclick', function(e) {
			var amount = this.sp.viewPort.containerH *.6;
			switch(e.direction) {
				case 'up': this.sp.viewPort.moveUp(amount); break;
				case 'down': this.sp.viewPort.moveDown(amount); break;
			}
		});
	}
	
	if (ua.ie6) {
		this.viewPort.container.sp = this;
		this.viewPort.container.onmousewheel = ScrollPort.wheelHandler;
	}
	
	this.timer = null;

	this.id = ScrollPort.all.length;
	ScrollPort.all[this.id] = this;
}

ScrollPort.all = [];
ScrollPort.prototype.toString = function () { return 'ScrollPort.all[' + this.id + ']' }

ScrollPort.prototype.isScrollable = function() {
	return this.viewPort.isScrollable();
}

ScrollPort.prototype.stopScroll = function() {
	clearTimeout(this.timer);
}

ScrollPort.prototype.scrollUp = function() {
	this._scrollCall = function() { this.viewPort.moveUp(this.amount)};
	this.time = (new Date()).getTime() - 50;
	this.doScroll();
}
ScrollPort.prototype.scrollDown = function() {
	this._scrollCall = function() { this.viewPort.moveDown(this.amount)} ;
	this.time = (new Date()).getTime() - 50;
	this.doScroll();
}

ScrollPort.prototype.doScroll = function() {
	var now = (new Date()).getTime();
	this.amount = this.conf.pixelspersecond * (now - this.time) / 1000;
	this._scrollCall();
	this.time = now;
	this.timer = setTimeout(this + '.doScroll()', this.conf.interval);
}


// EventHandlers
ScrollPort.buttonUpMousedownHandler = function(e) {
	this.sp.scrollUp();
	if (e && e.preventDefault) e.preventDefault();
	else return false;
}
ScrollPort.buttonDownMousedownHandler = function(e) {
	this.sp.scrollDown();
	if (e && e.preventDefault) e.preventDefault();
	else return false;
}
ScrollPort.stopScroll = function() {
	this.sp.stopScroll();
}

ScrollPort.wheelHandler = function() {
	if (event.wheelDelta > 0) this.sp.viewPort.moveUp(this.sp.conf.wheelstep);
	else this.sp.viewPort.moveDown(this.sp.conf.wheelstep);
	return false;
}




