/**
 * JSON RPC client
 * @param string url The location of the webservice
 */
PBJSONRPCClient = function (url, methods)
{
	this.url = url;
	
	if (methods) {
		var methods = $A(methods);
		
		this.genericMethod = function ()
		{
			return this.call.apply(this, arguments);
		};
	
		methods.each((function (method)
		{
			this[method] = this.genericMethod.curry(method);
		}).bind(this));
	}
}

/**
 * Initiates a remote procedure call to the specified method
 * @param string method The method to invoke
 * @param mixed arg Every next argument will be passed as an argument to the invoked method
 */
PBJSONRPCClient.prototype.realCall = function (aSync, method)
{
	var aSync = Object.isUndefined(aSync) ? false : aSync;
	var args = $A(arguments);
	args.shift();

	// Create the request object
	var content = {
		'jsonrpc': '2.0',
		'method': args.shift(),
		'params': args.toArray(),
		'id': new Date().getTime().toString()
	};

	// Initiate the request and return the result
	var response;
	new Ajax.Request(this.url, {
		'asynchronous': aSync,
		'contentType': 'application/json',
		'method': 'post',
		'postBody': Object.toJSON(content),
		'onSuccess': function (transport) {
			if (transport.responseJSON) {
				response = transport.responseJSON;
			} else {
				response = transport.responseText.evalJSON();
			}

			if (Object.isUndefined(response.result)) {
				response = {'result': null};
			}
		}
	});
	
	if (Object.isUndefined(response) || Object.isUndefined(response.result)) {
		return null;
	}
	
	return response.result;
}

PBJSONRPCClient.prototype.callAsync = PBJSONRPCClient.prototype.realCall.curry(true);
PBJSONRPCClient.prototype.call = PBJSONRPCClient.prototype.realCall.curry(false);