// JavaScript Document
function Odometer()
{
	this.aDigits;
	
	this.nShownValue = 0;
	this.nEndValue = 0;
	this.nSymbolHeight = 11;
	this.nRollTime = 10;
	
	this.ndSpeedIncrease = 0;
	this.nSpeed = 0;
	this.tmrUpdate = null;
	this.MIN_SPEED = 2;
	this.nStep = 0;
	this.nRollingDigitsCount = 0;

	this.oldVal = 0;
	this.newVal = 0;
	this.initialTop = 0;
	this.currentTop = 0;
	
	this.UPDATE_DELAY = 50;
	this.MONEY_SIGN = "$";
	this.MONEY_FRAGMENTS = 100;
}

Odometer.prototype.init = function( aDigits, strSign, nFragments, nSpeed, nUpdateDelay )
{
	this.aDigits = aDigits;
	this.nRollTime = nSpeed;
	
	this.UPDATE_DELAY = nUpdateDelay;
	this.MONEY_SIGN  =strSign;
	this.MONEY_FRAGMENTS = nFragments;
	
	this.nSymbolHeight = $( this.aDigits[0] ).height() / 2;
	this.initialTop = 0;//$( aDigits[0] ).position().top;
	this.currentTop = - this.nSymbolHeight;
	
	for ( var iDiv = 0; iDiv < this.aDigits.length; ++iDiv )
	{
		$( this.aDigits[iDiv] )
			.css( "visibility", "visible" )
			.css( "top", this.currentTop )
			.html( "" );
	}
}

Odometer.prototype.calculateStep = function()
{
	var nDistanceInPix = ( this.nEndValue - this.nShownValue ) * this.nSymbolHeight;
	var nNewSpeed = nDistanceInPix / this.nRollTime;
	
	if ( this.nSpeed < nNewSpeed )
	{
		nNewSpeed = this.nSpeed + this.ndSpeedIncrease;
	}

	this.nSpeed = ( nNewSpeed < this.MIN_SPEED ) ? this.MIN_SPEED : nNewSpeed; 			// check for min speed
	
	this.nStep = this.nSpeed / this.nSymbolHeight;
	this.nSpeed = (  this.nSymbolHeight < this.nSpeed ) ?  this.nSymbolHeight : this.nSpeed;
	this.nStep = ( 1 > this.nStep ) ? 1 : this.nStep; // Step must be at least 1
}
		
Odometer.prototype.setInitialValue = function( val )
{
	val = parseFloat( val  )
	this.nShownValue = val;
	val = val / this.MONEY_FRAGMENTS;
	val = this.MONEY_SIGN + val.formatMoney( 2, ".", "," );
	
	var adigits = String( val ).split("");
	var noffset = this.aDigits.length - adigits.length;

	for ( var i = 0; i < noffset; ++i )
	{
		$( this.aDigits[ this.aDigits.length - i - 1] )
			.hide()
		//	.css( "top", this.initialTop );
	}

	for ( var iLast = 0; iLast < adigits.length; ++iLast )
	{
		$( this.aDigits[ this.aDigits.length - noffset - 1 - iLast] )
			.html( adigits[iLast] + "<br/>" + adigits[iLast] )
			.show();
	}
}


Odometer.prototype.update = function()
{
	var $this  = this;
	var newTop = this.currentTop + this.nSpeed ;

	//console.log( this.initialTop + " : " + newTop + " : " + 2 * this.nSymbolHeight )
	if ( this.initialTop < newTop )
	{
		this.incrementValue();
		this.currentTop =  newTop -  this.nSymbolHeight ;
		//console.log( "currentTop: " + this.currentTop )
		if ( this.initialTop < this.currentTop  )
		{
			debugger;
		}
		for ( var iPos = 0; iPos < this.nRollingDigitsCount; ++iPos )
		{
			$( this.aDigits[ iPos ] ).css( "top", this.currentTop );
		}
	}
	else
	{
		for ( var iPos = 0; iPos < this.nRollingDigitsCount; ++iPos )
		{
			$( this.aDigits[ iPos ] ).css( "top", newTop );
		}
		this.currentTop = newTop;
	}
	
	this.calculateStep();

	if ( this.oldVal == this.nEndValue )
	{
		this.tmrUpdate = null;
		this.setInitialValue( this.nEndValue );
		this.nSpeed = 0;
	}
	else
	{
		this.tmrUpdate = setTimeout( function () { $this.update() }, this.UPDATE_DELAY );
	}
}
	
Odometer.prototype.disributeDigits = function( newVal, oldVal )
{
	newVal = newVal / this.MONEY_FRAGMENTS;
	newVal = this.MONEY_SIGN + newVal.formatMoney( 2, ".", "," );
	newVal = String( newVal ).split("");

	oldVal = oldVal / this.MONEY_FRAGMENTS;
	oldVal = this.MONEY_SIGN + oldVal.formatMoney( 2, ".", "," );
	oldVal = String( oldVal ).split("");
	
	for ( var iLast = 0; iLast < this.aDigits.length; ++iLast )
	{
		var v1 = ( iLast < newVal.length ) ? newVal[ newVal.length - 1 - iLast ] : "";
		var v2 = ( iLast < oldVal.length ) ? oldVal[ oldVal.length - 1 - iLast ] : "";
		$( this.aDigits[ iLast ] )
			.html( v1 + "<br/>" + v2 )
			.show();
	}
}

Odometer.prototype.updateValue = function( nNewValue )
{
	nNewValue = parseFloat( nNewValue )
	var $this = this;
	//console.log( "updateValue" );
	if ( nNewValue > this.nShownValue )
	{
		this.nEndValue = nNewValue;
		var nDistanceInPix = ( this.nEndValue - this.nShownValue ) * this.nSymbolHeight;
		var nNewSpeed = nDistanceInPix / this.nRollTime ;
		this.ndSpeedIncrease = ( nNewSpeed ) * 0.02;
		//this.ndSpeedIncrease = ( this.nSymbolHeight < this.ndSpeedIncrease) ? this.nSymbolHeight : this.ndSpeedIncrease;
		//console.log( "ndSpeedIncrease: " + ndSpeedIncrease);
		this.calculateStep();

		// Start rolling if counter is stoped 
		if ( null == this.tmrUpdate )
		{
			this.incrementValue();
			this.tmrUpdate = setTimeout( function () { $this.update() }, this.UPDATE_DELAY );
		}
	}
	else if ( nNewValue < this.nShownValue )
	{
		// New JP value is smaller than curret so show it
		this.setInitialValue( nNewValue );
	}
	else
	{
		// nNewValue = m_nEndValue - so do nothing
	}
}

Odometer.prototype.incrementValue = function()
{	
	var oldValue = ( this.MONEY_SIGN + ( this.nShownValue/ this.MONEY_FRAGMENTS ).formatMoney(2,".",",") ).split('');
	var nOldRollingDigits = this.nRollingDigitsCount;
	
	this.nRollingDigitsCount = 0;
	this.oldVal = this.nShownValue;

	this.nShownValue += this.nStep; 
	this.nShownValue = ( this.nShownValue > this.nEndValue ) ? this.nEndValue : this.nShownValue;

	this.newVal = this.nShownValue;
	
	this.disributeDigits( this.newVal, this.oldVal );
	var anNewShownValue = ( this.MONEY_SIGN + ( this.nShownValue / this.MONEY_FRAGMENTS ).formatMoney( 2, ".", "," ) ).split('');
	
	if ( anNewShownValue.length == oldValue.length )
	{
		for ( var iPos = oldValue.length - 1; iPos >= 0; --iPos )
		{
			if ( oldValue[ iPos ] != anNewShownValue[ iPos ] )
			{
				++this.nRollingDigitsCount;  // must have at least 1 differrent digit
			}
		}
	}
	else
	{
		this.nRollingDigitsCount = anNewShownValue.length;
	}
	
	if ( nOldRollingDigits > this.nRollingDigitsCount )
	{
		for ( var i = this.nRollingDigitsCount; i < nOldRollingDigits; ++i )
		{
			$( this.aDigits[  i ] ).css( "top", this.initialTop )
		}
	}
}
		
	
