var start_time = 0;
var bandwidth = 0;

function Timer()
{
	this.startTime = 0;
	this.endTime = 0;

	Timer.prototype.Reset = function()
	{
		this.startTime = new Date().getTime();
		this.endTime = 0;
	}

	Timer.prototype.Stop = function()
	{
		this.endTime = new Date().getTime();
		return this.endTime - this.startTime;
	}

	Timer.prototype.Value = function()
	{
		var end = this.endTime;
		if( end == 0 && this.startTime != 0 )
			end = new Date().getTime();
		return end - this.startTime;
	}

	this.Reset();
}

Number.prototype.timeString = function()
{
	if( this >= 1000 )
		return roundNumber( this / 1000, 2 ).toString() + " s";
	return this.toString() + " ms";
}

Number.prototype.speedString = function()
{
    if( this >= 1000 )
        return roundNumber( this / 1000, 1 ).toString() + " Mbit/s";
    return this.toString() + " kbit/s";
}

function WebClientRequest( method, url )
{
	this.timer = new Timer;
	this.url = url;
	this.data = "";
	this.method = method;

	this.GetResponse = function( readData )
	{
		var response = new WebClientResponse( this, readData );
		this.timer.Reset();
		$.ajax( {
			url: this.url,
			cache: false,
			async: false,
			processData: false,
			data: this.data,
			type: this.method,
			dataType: "text",
			contentType: "text/plain; charset=x-user-defined",
			complete: response.InternalRequestCompleted(),
			error: function( e ) 
			{
				if( e.status == 200 )
					return; // We do get here in IE7 on Vista, even though the request performed well..
				if( e.status == 405 )
					alert( "Your web server does not allow HTTP POST to this HTML file.\nPlease review your configuration." );
			} 
		} );

		return response;
	};
}

function WebClientResponse( request, readData )
{
	this.request = request;
	this.readData = readData;
	this.data = "";
	this.status = "";
	this.statusText = "";
	this.contentLength = 0;
	this.bytesTransferred = 0;
	this.GetTime = function() { return this.request.timer.Value(); }
	this.GetSpeed = function() { return roundNumber( ( this.bytesTransferred * 0.008 ) / ( this.GetTime() / 1000 ), 0 ); }

	this.InternalRequestCompleted = function() 
	{
		var response = this;
		return function( xhr )
		{
			response.status = xhr.status;
			response.statusText = xhr.statusText;
			var contentLengthHeader = xhr.getResponseHeader( "Content-Length" );
			
			if( null != contentLengthHeader && contentLengthHeader.length > 0 )
				response.contentLength = parseInt( contentLengthHeader );
			else if( null != xhr.responseText )
				response.contentLength = xhr.responseText.length;
			else
				response.contentLength = 0;
			
			if( response.request.method == "POST" )
				response.contentLength = request.data.length;
			if( response.request.method != "HEAD" )
				response.bytesTransferred = response.contentLength;
			if( response.readData )
				response.data = xhr.responseText;
			response.request.timer.Stop();
		}
    };
}

function roundNumber(num, dec) 
{
  var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
  return result;
}


/**
 * Brainsonic Bandwidth tester
 * 
 * @param file         url to file for test 
 * @param cookieName   cookie name
 * @param iteration    number of request for bandwidth test
 * @param timeout      if test duration is greater, return O bandwidth value
 * @return
 */

function BandwidthTester(file, cookieName, iteration, timeout)
{
	if(file == undefined)
	{
		throw 'no file path passed for bandwidth test';
	}
	this.file = file;
	
	this.iteration = iteration == undefined ? 4 : iteration;
	this.timeout = timeout == undefined ? 1000 : timeout;
	this.cookieName = cookieName == undefined ? 'brainsonic' : cookieName;
	this.timer = new Timer();
}

BandwidthTester.prototype.launch = function(callback)
{
	var bandwidth = 0;
	if(typeof $.Jookie == 'object')
	{
		$.Jookie.Initialise(this.cookieName, 60);
		if($.Jookie.Get(this.cookieName, 'bandwidth') == undefined)
		{
			$.Jookie.Set(this.cookieName, 'bandwidth', this.test());
		}
		bandwidth = $.Jookie.Get(this.cookieName, 'bandwidth');
		
	}
	callback(bandwidth);
}

BandwidthTester.prototype.test = function()
{
	this.timer.Reset();
	var bp = 0;
	for(var i=0 ; i<this.iteration ; i++)
	{
		if(this.timer.Value() > this.timeout)
		{
			return 0;
		}
		var clientRequest  = new WebClientRequest('GET', this.file);
		var clientResponse = clientRequest.GetResponse();
		bp = eval(clientResponse.GetSpeed() + bp);
	}
	return bp / this.iteration;
}
