var request = require( "request" ),
	querystring = require( "querystring" ).stringify,
	urlparse = require( "url" ).parse;

function extend( a, b ) {
	for (var key in b) {
		a[key] = b[key];
	}
	return a;
}

function continueRunning( job ) {
	return job.runs.filter(function( run ) {
		return Object.keys(run.uaRuns).filter(function( uaRun ) {
			return (/new|progress/).test( run.uaRuns[ uaRun ].runStatus );
		}).length;
	}).length;
}

function logResults( config, job, state ) {
	var passed = true;
	console.log( "Job " + job.jobInfo.id + ":\n\t" + job.jobInfo.name + "\nState: " + state );
	console.log( "\nResults: " );
	job.runs.filter(function( run ) {
		var uaID;
		console.log( "\n - " + run.info.name + ":\n", run.uaRuns );
		for ( uaID in run.uaRuns ) {
			// "new", "failed", "error", "timedout", ..
			if ( run.uaRuns[uaID].runStatus !== "passed" ) {
				passed = false;
			}
		}
	});
	config.done( passed );
}

function pollResults( config, job ) {
	process.stdout.write( "." );
	request.get( config.url + "/api.php?" + querystring({
		action: "job",
		item: job.id
	}), function ( error, response, body ) {
		if ( error ) {
			throw error;
		}
		var result = JSON.parse( body );
		if ( !result.job ) {
			console.log( "API returned error, can't continue. Response was: " + body );
			config.done( false );
			return;
		}
		if ( continueRunning( result.job ) ) {
			if ( config.started + config.timeout < +new Date() ) {
				process.stdout.write( "\n\n" );
				logResults( config, result.job, "Timed out after " + config.timeout + 'ms' );
			}
			setTimeout(function () {
				pollResults( config, job );
			}, config.pollInterval );
		} else {
			process.stdout.write( "\n\n" );
			logResults( config, result.job, "Finished" );
		}
	});
}

module.exports = function ( config, addjobParams ) {
	config = extend({
		// default config
		//url: {String} required, no default
		//done: {Function} required, no default
		pollInterval: 5000,
		timeout: 1000 * 60 * 15, // 15 minutes
		started: +new Date(),
		urlParts: urlparse( config.url )
	}, config);
	addjobParams = extend(addjobParams, {
		action: "addjob"
	});
	request.post( config.url + "/api.php?" + querystring( addjobParams ), function ( error, response, body ) {
		var result, jobInfo;
		if ( error ) {
			throw error;
		}
		result = JSON.parse( body );
		if ( !result.addjob ) {
			console.log( "API returned error, can't continue. Response was: " + body );
			config.done( false );
			return;
		}
		jobInfo = result.addjob;
		console.log( "Submited job " + jobInfo.id + " " + config.url + "/job/" + jobInfo.id );
		process.stdout.write( "Polling for results" );
		pollResults( config, jobInfo );
	});

};

@@ -427,24 +427,228 @@
 .length;%0A%7D%0A%0A
+function runStats( uaID, uaRun ) %7B%0A%09var base = uaID + %22: %22 + uaRun.runStatus;%0A%09if ( uaRun.runResultsUrl ) %7B%0A%09%09base +=  %22 (%22 + uaRun.runResultsLabel + %22)%22 + %22: %22 + uaRun.runResultsUrl;%0A%09%7D%0A%09return base;%0A%7D%0A%0A
 function log
@@ -675,24 +675,24 @@
 , state ) %7B%0A
-
 %09var passed 
@@ -916,12 +916,28 @@
 + %22:
-%5Cn%22,
+%22 );%0A%09%09for ( uaID in
  run
@@ -945,33 +945,50 @@
 uaRuns )
-;%0A%09%09for 
+ %7B%0A%09%09%09console.log( runStats
 ( uaID
- in
+,
  run.uaR
@@ -986,28 +986,35 @@
 , run.uaRuns
+%5BuaID%5D
  ) 
-%7B
+);
 %0A%09%09%09// %22new%22

Compress results output