if(!window.console) window.console = {
	log: function(s) {alert(s)}
}
function BaseMovil(pos, frictionForce, lowerLimit, upperLimit, speedLimit) {
	//Config
	speedLimit = (speedLimit!=null)? speedLimit : Infinity
	lowerLimit = (lowerLimit!=null)? lowerLimit : -Infinity	
	upperLimit = (upperLimit!=null)? upperLimit : Infinity		
	frictionForce = Math.abs(frictionForce) || 0
	var force = 0
	//state
	var speed0 = 0
	var time0 = (new Date()).getTime()
	var pos0 = pos || 0
	//constant calculated values
	var totalForce
	var timeLimit
	var nextSpeed0 = null

	function logStatus() {
		/*console.log('speed0: '+speed0)
		console.log('time0: '+time0)		
		console.log('pos: '+pos)				
		console.log('timeLimit: '+timeLimit)
		console.log('totalForce: '+totalForce)	
		console.log('-----------------')			*/
	}

	function sign(num) {
		if(num==0) return 0
		if(num>0) return 1
		else return -1
	}
	function calcFriction() {
		if(speed0 != 0) return (-sign(speed0))*frictionForce
		else {
			if(Math.abs(force)>frictionForce) return (-sign(force))*frictionForce
			else return -force
		}
	}
	function calcConstants() {
		totalForce = force + calcFriction()
		if(totalForce==0) {
			timeLimit = Infinity
			nextSpeed0 = speed0
		} else {
			if((totalForce*speed0)<0) {
				//Stopping
				timeLimit = time0 - (speed0/totalForce)
				nextSpeed0 = 0
			} else {
				if(totalForce>0) {
					timeLimit = time0 + ((speedLimit-speed0)/totalForce)
					nextSpeed0 = speedLimit
				} else {
					timeLimit = time0 - ((speedLimit+speed0)/totalForce)
					nextSpeed0 = -speedLimit					
				}
			}
		}
	}
	
	function speedAt(dt) {
//		console.log('dt: '+(time - time0)+' speed0: '+speed0+' speed: '+(totalForce*(time - time0) + speed0))
		return totalForce*dt + speed0
	}
	function positionAt(dt) {
//		console.log('positionAt: '+(pos -  ( (totalForce*time*time)/2 ) +time*speed))
		return pos0 +  dt*( speed0 + (totalForce*dt)/2 )
	}
	calcConstants()
	this.pos = function(t) {
		var time = t || (new Date()).getTime()
		var dt = time - time0
		if(time<timeLimit) {
			var position = positionAt(dt)
			if(position>upperLimit) {
				pos0 = upperLimit
				speed0 = 0
				time0 = time
				force = 0
				calcConstants()
				//console.log('position: '+pos)
				return upperLimit
			} else {
				if(position<lowerLimit) { 
					pos0 = lowerLimit
					speed0 = 0
					time0 = time
					force = 0
					calcConstants()
					//console.log('position: '+pos)
					return lowerLimit
				} else {
					//console.log('position: '+position)
					return position
				}
			}
		} else {
			//No son validos mis calculos
			//console.log('Calculos no validos - t = '+time)			
	
			pos0 = positionAt(timeLimit-time0)
			speed0 = nextSpeed0
			time0 = timeLimit
			calcConstants()
			var position = this.pos(time)
			//console.log('position: '+position)
			return position
		}
	}
	this.setForce = function(f) {
		var time = (new Date()).getTime()
		var dt = time-time0
		var currentSpeed = speedAt(dt)
		pos0 = positionAt(dt)
		speed0 = currentSpeed
		time0 = time
		force = f
		calcConstants()
	}
	this.addForce = function(f) {
		this.setForce(force + f)
	}			
	this.force = function() {
		return force;
	}
	this.speed = function(t) {
		var time = t || (new Date()).getTime()
		if(time<timeLimit) {
			return speedAt(time-time0)
		} else {
			//No son validos mis calculos
			pos0 = positionAt(timeLimit-time0)
			speed0 = nextSpeed0
			time0 = timeLimit
			calcConstants()
			return this.speed(time)
		}

	}
	this.stop = function() {
		var time = (new Date()).getTime()
		pos = this.pos(time-time0)
		speed0 = 0
		time0 = time
		force = 0
		calcConstants()
	}
	this.setSpeed = function(s) {
		var time = (new Date()).getTime()
		var currentSpeed = speedAt(time-time0)
		pos = this.pos(time)
		speed0 = currentSpeed
		time0 = time
		calcConstants()
	}
	this.setPosition = function(p) {
		pos = p
	}
}
function Movil(settings) {
	var movil = new BaseMovil(
		settings.position, 
		settings.friction, 
		settings.lowerLimit, 
		settings.upperLimit,
		settings.speedLimit)
	var moving = false
	var mySelf = this

	function handle() {
		if(movil.speed()==0 && movil.force()==0) {
			moving = false
		} else {
			setTimeout(handle, 0)
		}
		settings.onchange(mySelf)
	} 
	function startObserving() {
		setTimeout(handle, 0)
	}
	this.pos = function() {
		return movil.pos()
	}
	this.setForce = function(f) {
		if(moving) {
			movil.setForce(f)
		} else {
			if(f!=0) startObserving()
			movil.setForce(f)
		}
	}
	this.addForce = function(f) {
		this.setForce(movil.force()+f)
	}			
	this.force = function() {
		return movil.force();
	}
	this.speed = function() {
		return movil.speed()
	}
	this.stop = function() {
		movil.stop()
	}
	this.setSpeed = function(s) {
		movil.setSpeed(s)		
	}
	this.setPosition = function(p) {
		movil.setPosition(p)
	}	
}

function Movil2D(posX, posY, friction, onchange) {
	var movilX = new BaseMovil(posX, friction)
	var movilY = new BaseMovil(posY, friction)	
	var moving = false
	var interval = null
	var mySelf = this
	function handle() {
		if(movilX.speed()==0 && movilY.speed()==0 && movilX.force()==0 && movilY.force()==0) {
			stopObserving()
			moving = false
		}
		onchange(mySelf)
	} 
	function startObserving() {
		if(interval!=null) return
		interval = setInterval(handle, 0)
	}
	function stopObserving() {
		if(interval==null) return
		clearInterval(interval)
		interval = null
	}
	this.posX = function() {
		return movilX.pos()
	}
	this.posY = function() {
		return movilY.pos()
	}	
	this.setForce = function(fx, fy) {
		if(moving) {
			movilX.setForce(fx)
			movilY.setForce(fy)			
		} else {
			if(fx!=0 || fy!=0) startObserving()
			movilX.setForce(fx)
			movilY.setForce(fy)			
		}
	}
	this.addForceX = function(f) {
		this.setForce(movilX.force()+f, movilY.force())
	}
	this.addForceY = function(f) {
		this.setForce(movilX.force(), movilY.force()+f)
	}	
	this.forceX = function() {
		return movilX.force();
	}
	this.forceY = function() {
		return movilY.force();
	}	
	this.speedX = function() {
		return movilX.speed()
	}
	this.speedY = function() {
		return movilY.speed()
	}	
	this.stop = function() {
		movilX.stop()
		movilY.stop()		
	}
	this.setSpeedX = function(s) {
		movilX.setSpeed(s)		
	}
	this.setSpeedY = function(s) {
		movilY.setSpeed(s)		
	}	
	this.setPosition = function(px, py) {
		movilX.setPosition(px)
		movilY.setPosition(py)		
	}
}
