if (typeof CAP == 'undefined') {
	YAHOO.namespace('CAP');
	CAP = YAHOO.CAP;
	CAP.util = {};
}

CAP.util.JsonBroker = function(sUrl, timeout)
{
	if (typeof timeout == 'undefined')
		timeout = 5000;

	this._sUrl = sUrl;
	this._timeout = timeout;
	this._debug = false;

	if (this._debug)
		console.info('JsonBroker: Instanciated url ',sUrl, ' and timeout ', timeout);
};

CAP.util.JsonBroker.prototype = {

	/**
	 * Change the url of the broker
	 * @param string newUrl: the new url that will be used for making the rpc calls
	 */
	setUrl: function(newUrl){
		this._sUrl = newUrl;
	},
	
	/**
	 * Calls a JSON rpc method on the server and fires the callback with the result.
	 * @param method: string - name of the server method to call. (e.g. "multiply")
	 * @param params: Array - List Array of the arguments for the RPC method
	 * @param cbSuccess: Function - Callback with the result
	 * @param cbFailure: Function - Callback with a Failure object
	 * @param scope: Object - The callbacks will be executed in the context of 'scope'
	 * @param timeout: Int - Timeout only for this call
	 * @param cbArg: Mixed - Arguments that are passed into the callback but wont be send to the server.
	 */
	call: function(method, params, cbSuccess, cbFailure, scope, timeout, cbArg){
	
		if (typeof scope == 'undefined') 
			scope = null;
		
		if (!(params instanceof Array)) 
			throw 'params must be an Array';
		
		if (this._debug) 
			console.info('JsonBroker: calling ' + method);
		
		// default failure handler
		if (typeof cbFailure == 'undefined' || !cbFailure) 
			cbFailure = this._handle_failure;
		
		if (!timeout) 
			timeout = this._timeout;
		
		if (typeof cbArg == 'undefined') 
			cbArg = null;
		
		/**
		 * Define the callback object which will be passed into the yahoo asyncRequest method.
		 * The server calls the .sucess method with a result object. This contains the result.responseText
		 * which is the json encoded result. This is eval'ed and called as an argument of the user callback method.
		 */
		var callback = {
			success: function(result){
			
				// json decode the server responsetext
				try {
					var response = YAHOO.lang.JSON.parse(result.responseText);
				} 
				catch (e) {
					throw new Error('JsonRPC: unable to parse response: ' + response);
				}
				
				if (response && (typeof response.exception != 'undefined')) {
					// in case we got an exception call the failure callback with a failure object defined in
					// http://developer.yahoo.com/yui/connection/#failure
					var failure = {
						tId: result.tId,
						status: 0,
						statusText: response.exception.message,
						statusType: response.exception.type,
						argument: []
					};
					cbFailure.call(scope, failure);
				}
				else 
					if (typeof cbSuccess != 'undefined' && cbSuccess) {
						// normal cases, just callback with the response object and extra callback args
						cbSuccess.call(scope, response, cbArg);
					}
			},
			failure: cbFailure,
			timeout: timeout
		};
		
		// Object containing method and params which will be json encoded and send as data string
		var data = {
			method: method,
			params: params
		};
		
		try {
			data_str = YAHOO.lang.JSON.stringify(data);
		} 
		catch (e) {
			console.error('JsonRPC: Unable to JSON stringify data', data)
			throw new Error('JsonRPC: Cannot stringify data');
		}
		
		// this sends the call to the server
		YAHOO.util.Connect.asyncRequest('POST', this._sUrl, callback, data_str);
	},
	
	/**
	 * Default failure handler for json requests
	 */
	_handle_failure: function(failure){
		console.error('JsonRPC: ', failure);
	}
};

YAHOO.register("iq_jsonrpc", CAP.util.JsonBroker, {version: "1.0.0", build: "1"});

