/* 
 *	@copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * 	@autor: Vasily Mamaevsky (polochka@design.ru)
 *
 *	Requires:
 *	- jquery
 */
function MovingAverage(size) {
	var stack = [];
	
	function _push(val) {
		if (stack.length >= size)
			stack.shift();
		stack.push(val);
	}
	function _pop(){ return stack.pop(); }
	function _clear() { stack = []; }
	
	function _getAverage() {
		var sum = 0;	
		for (var i in stack)
			sum += stack[i];
		
		var len = stack.length;
		if (len != 0) {
			return sum/len;
		} else
			return 0;
	}
	
	function _debug() {
		var tmp = '';
		for (var i in stack) {
			tmp += i + ': ' + stack[i] + '; ';
		}
		tmp += 'len: ' + stack.length + '; ';
		tmp += 'avg: ' + _getAverage() + ' |';
		
		return tmp;
	}
	
	return {
		pushVal: _push,
		popVal: _pop,
		clear: _clear,
		getAverage: _getAverage,
		debug: _debug
	}
}

function MouseVelocityMeter (selector) {
	// Объект, к которому привязывается спидометр
	// По умолчанию: весь документ	
	var obj = (typeof(selector) == 'undefined' ? $(document) : $(selector));

	var velocityMovingAverage = new MovingAverage(10);

	// Всякая служебная ерунда
	var dragMode = false,
		x1 = 0,
		x2 = 0,
		lastX = 0,
		lastDate = null;
	
	
	/* 
	 *	Обработчики событий
	 */
	$(document).mouseup(function(e) {
		if (dragMode) {
			PushMouseSpeed(e);
		}
		
		dragMode = false;
	});
	
	$(document).mousemove(function(e){ 
		if (dragMode) PushMouseSpeed(e);
	});
	
	obj.mousedown(function(e){
		// старые результаты удаляются перед началом нового цикла вычислений
		velocityMovingAverage.clear();
		
		if (!dragMode) {
			lastDate = new Date();
			PushMouseSpeed(e);
			x2 = e.pageX;
		}
		
		dragMode = true;
	});
	
	
	/*
	 * 	Тут считывается скорость в пикселях/мс
	 */
	function PushMouseSpeed(e) {
		if (dragMode) {
			var vel = 0;
			
			lastX = e.pageX;
			
			x1 = x2;
			x2 = lastX;
			
			var new_date = new Date();
			var time_interval = new_date.getTime() - lastDate.getTime();
			lastDate = new_date;
			
			if (time_interval >= 100) velocityMovingAverage.clear();
			else {
				if (time_interval > 2) vel = (x2 - x1) / time_interval;
				else vel = 0;
				if (vel != 0 && !isNaN(vel)) velocityMovingAverage.pushVal(vel);
			}
		}
	}
	
	
	/*
	 *	Тадам!
	 */
	return {
		getV: function() {
			return velocityMovingAverage.getAverage();
		}
	}
}
