//*** CLASS Projection **************************************************
function Projection(id, parent, width, height, fontsize, vanishX, vanishY, vanishZ, speed) {
	this._id = id;
	this._parent = parent; //object that conforms to interface ProjectionUser (see documentation).
	
	//the three-dimensional current position in a virtual space
	this._posX = 0;
	this._posY = 0;
	this._posZ = 0;
	//a target point (to move to) in virtual space
	this._targetPosX = 0;
	this._targetPosY = 0;
	this._targetPosZ = 0;
	this._speed = speed;
	//static sizes in virtual space
	this._width = width;
	this._height = height;
	this._fontsize = fontsize;
	//TODO:
	//background and font colors could be projected, too, if that doesn't drop performance.
	
	//a vanishing point in a space (Fluchtpunkt) on a per avatar basis for flexibility
	this._vanishX = vanishX;
	this._vanishY = vanishY;
	this._vanishZ = vanishZ;
	
	//the two-dimensional projection to a screen-position and size.
	this._projectedX = 0;
	this._projectedY = 0;
	this._projectedWidth = 0;
	this._projectedHeight = 0;
	this._projectedFontsize = 0;
	this._movementVectorX = 0;
	this._movementVectorY = 0;
	this._movementVectorZ = 0;
}

Projection.prototype._id;
Projection.prototype._parent;
Projection.prototype._posX;
Projection.prototype._posY;
Projection.prototype._posZ;
Projection.prototype._targetPosX;
Projection.prototype._targetPosY;
Projection.prototype._targetPosZ;
Projection.prototype._speed;
Projection.prototype._width;
Projection.prototype._height;
Projection.prototype._fontsize;
Projection.prototype._vanishX;
Projection.prototype._vanishY;
Projection.prototype._vanishZ;
Projection.prototype._projectedX;
Projection.prototype._projectedY;
Projection.prototype._projectedWidth;
Projection.prototype._projectedHeight;
Projection.prototype._projectedFontsize;
Projection.prototype._movementVectorX;
Projection.prototype._movementVectorY;
Projection.prototype._movementVectorZ;

//class methods
Projection.prototype.set3DPosition = function(x, y, z) { 
	this._posX = parseInt(x);
	this._posY = parseInt(y);
	this._posZ = parseInt(z);
	
	this.projection();
}

Projection.prototype.setTargetPosition = function(x, y, z) { 
	this._targetPosX = parseInt(x);
	this._targetPosY = parseInt(y);
	this._targetPosZ = parseInt(z);
}

Projection.prototype.projection = function() { 
	//project 3D virtual coordinates to 2D screen-position and object size
	//using vanishing point projection (Fluchtpunktverfahren basierend auf Strahlensaetzen).
	var vanishX = this._vanishX;
	var vanishY = this._vanishY;
	var vanishZ = this._vanishZ;
	
	this._projectedX = parseInt( ( ((this._posX - vanishX) * vanishZ) / (vanishZ - this._posZ) ) + vanishX );
	this._projectedY = parseInt( ( ((this._posY - vanishY) * vanishZ) / (vanishZ - this._posZ) ) + vanishY );
	this._projectedWidth = -(this._projectedX) + parseInt( ( ((this._posX+this._width - vanishX) * vanishZ) / (vanishZ - this._posZ) ) + vanishX ); 
	this._projectedHeight = -(this._projectedY) + parseInt( ( ((this._posY+this._height - vanishY) * vanishZ) / (vanishZ - this._posZ) ) + vanishY );
	var newFontsize = -(this._projectedY) + parseInt( ( ((this._posY+this._fontsize - vanishY) * vanishZ) / (vanishZ - this._posZ) ) + vanishY );
	//anti-flicker orientation guessing ("normalizes" sizing)
	//if( (newFontsize < this._projectedFontsize  && this._movementVectorZ > 0)
	//		|| (newFontsize > this._projectedFontsize  && this._movementVectorZ < 0)	) {
		this._projectedFontsize = newFontsize;
	//}
	this._parent.updateDOM();
}//pojection

Projection.prototype.moveToTarget = function() {
		//var deltaX = (this._targetPosX - this._posX) / (100 / this._speed);
		//var deltaY = (this._targetPosY - this._posY) / (100 / this._speed);
		//var deltaZ = (this._targetPosZ - this._posZ) / (100 / this._speed);
		this._movementVectorX = (this._targetPosX - this._posX) / (100 / this._speed);
		this._movementVectorY = (this._targetPosY - this._posY) / (100 / this._speed);
		this._movementVectorZ = (this._targetPosZ - this._posZ) / (100 / this._speed);
		
		if(this._movementVectorX > 0 && this._movementVectorX < 1) { this._movementVectorX = 1 };
		if(this._movementVectorY > 0 && this._movementVectorY < 1) { this._movementVectorY = 1 };
		if(this._movementVectorZ > 0 && this._movementVectorZ < 1) { this._movementVectorZ = 1 };
		if(this._movementVectorX < 0 && this._movementVectorX > -1) { this._movementVectorX = -1 };
		if(this._movementVectorY < 0 && this._movementVectorY > -1) { this._movementVectorY = -1 };
		if(this._movementVectorZ < 0 && this._movementVectorZ > -1) { this._movementVectorZ = -1 };
		
		//this.set3DPosition(this._posX + deltaX, this._posY + deltaY, this._posZ + deltaZ);
		this.set3DPosition(this._posX + this._movementVectorX, this._posY + this._movementVectorY, this._posZ + this._movementVectorZ);
		
		//reached target position
		if( (this._posX == this._targetPosX) && (this._posY == this._targetPosY) && (this._posZ == this._targetPosZ) ) {
			
			//let delegation object decide what to do now
			this._parent.reachedTarget();
		}//if
}//moveToTarget

Projection.prototype.stepToTarget = function() {
		var deltaX = (this._targetPosX - this._posX) / (100 / this._speed);
		var deltaY = (this._targetPosY - this._posY) / (100 / this._speed);
		var deltaZ = (this._targetPosZ - this._posZ) / (100 / this._speed);
		
		if(deltaX > 0 && deltaX < 1) { deltaX = 1 };
		if(deltaY > 0 && deltaY < 1) { deltaY = 1 };
		if(deltaZ > 0 && deltaZ < 1) { deltaZ = 1 };
		if(deltaX < 0 && deltaX > -1) { deltaX = -1 };
		if(deltaY < 0 && deltaY > -1) { deltaY = -1 };
		if(deltaZ < 0 && deltaZ > -1) { deltaZ = -1 };
		
		this.set3DPosition(this._posX + deltaX, this._posY + deltaY, this._posZ + deltaZ);
		
		//reached target position
		if( (this._posX == this._targetPosX) && (this._posY == this._targetPosY) && (this._posZ == this._targetPosZ) ) {
			
			//let delegation object decide what to do now
			this._parent.reachedTarget();
		}//if
}//stepToTarget
//*** END CLASS Projection *************************************************
