/*	
	Action harness
	Programmed by Roman Mitasov
	Algorithm and common conception based on class delay_move by Maxim Popov - ecto.ru
	
	
	Any stream is:
	[0]=callback		-	callback processing function
	[1]=int				-	from
	[2]=int				-	to
[	[3]=callback		-	befor start						]
[	[4]=callback		-	after finish					]
[	[5]=int				-	max speed						]
[	[6]=int				-	acceleration					]
	
*/
function harness(){
	var aStreams=new Array();
	var iCurStream=0;
	var fInAction=false;
	var pTmr;
	
	var iSrc=0;
	var iDst=0;
	
	var fnCallBack=null;
	var fnBefore=null;
	var fnAfter=null;
	
	var iDifference=0;
	var iHalfDifference=0;
	var fHalf=false;
	
	var iSpeed;
	var iMaxSpeed;
	var iAcceleration;
	
	var iProgress;

	var iDefaultMaxSpeed=20;
	var iDefaultAcceleration=3;

	this.addStream=function (aStream){
		aStreams.push(aStream);
	}
	
	this.action=function(){
		if(fInAction)
			return false;
		fInAction=true;
		iCurStream=0;
		return activate(0);
	}
	
	function activate(iStream){
		if(!aStreams[iStream])
			return false;
			
		iSrc=aStreams[iStream][1];
		iDst=aStreams[iStream][2];
		
		fnCallBack=aStreams[iStream][0];
		fnBefore=null;
		if(aStreams[iStream][3])
			fnBefore=aStreams[iStream][3];
		
		fnAfter=null;
		if(aStreams[iStream][4])
			fnAfter=aStreams[iStream][4];
		
		
		iDifference=iDst-iSrc;
		iHalfDifference=iDifference/2;
		
		iSpeed=0;
		iProgress=iSrc;
		
		if(aStreams[iStream][5])
			iMaxSpeed=aStreams[iStream][5];
		else
			iMaxSpeed=iDefaultMaxSpeed;
		
		if(aStreams[iStream][6])
			iAcceleration=aStreams[iStream][6];
		else
			iAcceleration=iDefaultAcceleration;
		
		if(fnBefore!=null)
			fnBefore();
		
		pTmr=window.setInterval(calculator, 15);
	}
	
	function calculator(){
		iPath=iDst-iProgress;
		if(iPath<=1){
			fnCallBack(iDst);
			window.clearInterval(pTmr);
		
			if(fnAfter!=null)
				fnAfter();
			
			if(!activate(++iCurStream)){
				fInAction=false;
			}
			return false;
		}
		
		if(iPath>iHalfDifference){
			iSpeed=(iDifference-iPath)/iAcceleration+0.5;
		}else{
			iSpeed=iPath/iAcceleration+0.5;
		}
		
		if(iSpeed>iMaxSpeed){
			iSpeed=iMaxSpeed;
		}
		
		if(iSpeed<0.1){
			iSpeed=0.1;
		}
		
		iProgress+=iSpeed;
		
		fnCallBack(iProgress);
	}
}

