/**
 * @namespace
 * UserAccounts
 **/
if(!window.UA) 	UA = {};
//======================================================================================
/**
 * @abscract-class 
 * It is a base-class of request worker-objects.
 * The goal of this classes is to allow multiple asyncronous calls on the same 
 * caller-object-instance, and aid in making the Asyncronous work as transparent as 
 * possible, means to make the callback functions run on the caller-object-instance,
 * A.K.A - this.boss.
 *
 * Jast.Request calls the event handlers on the carrier object they are delivered on. 
 * This class decendents pass thier calls to thier "boss" - the caller-instance.
 *
 * To send the request - the caller class calls the apply method.
 **/

UA.Request = Class.create();

/*    static members	*/
//-------------------------------------------------------------
/**
 * Status OK for OK Jast requests
 **/
UA.Request.STATUS_OK = "OK";
/**
 * Status GENERAL_ERROR
 **/
UA.Request.STATUS_GENERAL_ERROR = "GENERAL_ERROR";
/*    static members	*/
//-------------------------------------------------------------
/**
 * overrides object.toString() as a static member to provide the class name
 **/
UA.Request.toString = function(){
    return "UA.Request";
}
/**
 * returns a stub instance, handy only to be a prototype instance
 **/
UA.Request.AsPrototype = function(){
    return new UA.Request({},new Function());
}
/*    Constructors  	*/
//-------------------------------------------------------------
/**
 * 
 **/
UA.Request.prototype.initialize = function( oBoss	, fSuccessCallback , fFailCallback, fTimeoutCallback){
    this.log = Object.extend({},this.log);
   	this.boss = this.log.boss = oBoss;
	/**
	 * Event handler stacks
	 **/
	this.successCallbacks = [];
	this.failiorCallbacks = [];
	this.timeoutCallbacks = [];

    Claim.isFunction(fSuccessCallback, "fSuccessCallback not provided in constructor for: " + this.toString() );
	this.successCallbacks.push(fSuccessCallback);

    if( !fFailCallback ) fFailCallback = oBoss.defaultOnFailior; 
    if( typeof(fFailCallback) == 'function') this.failiorCallbacks.push( fFailCallback );
    
    if( !fTimeoutCallback ) fTimeoutCallback = oBoss.defaultOnTimeout; 
    if( typeof(fTimeoutCallback) == 'function') this.timeoutCallbacks.push( fTimeoutCallback );
    
    this.parameters = {};
}

/*    instance members	*/
//-------------------------------------------------------------
/*
	--	@private	{[object]}	log
	--	@private	{string}	url
	--				{boolean}	isSent
	--				{[Array]}	successCallbacks
	--				{[Array]}	failiorCallbacks
	--				{[Array]}	timeoutCallbacks
*/
/**
 * @private 
 * passes log calls to the log of the "boss"
 **/
UA.Request.prototype.log =  { emit:	 function(iLevel,sText){
										if(this.boss.log && typeof(this.boss.log.emit) == 'function'){
											this.boss.log.emit(iLevel, sText);
										}else 
											this.log.error("Cannot log for caller-object: " + this.boss.toString() + ". Level: " +iLevel+ ", Message: " + sText);
									 } 
							, fatal: function(sText){ this.emit(Log4Js.FATAL, sText); }
							, error: function(sText){ this.emit(Log4Js.ERROR, sText); }
							, warn:	 function(sText){ this.emit(Log4Js.WARN , sText); }
							, info:	 function(sText){ this.emit(Log4Js.INFO , sText); }
							, debug: function(sText){ this.emit(Log4Js.DEBUG, sText); }
							, log: new Log4Js.Logger("UA.Request.log")
							, boss: null
							, toString: function(){ return "UA.Request.log"; }
							}
/**
 * @private {string}
 * The url for the Just request
 * Its expected to be initiated in the overriding "initialize(boss)" method.
 **/
UA.Request.prototype.url = "UNSET-VALUE";

/**
 * States if the current instance was sent.
 **/
UA.Request.prototype.isSent = false;



/*    private functions	*/
//-------------------------------------------------------------
/*
	--	dispatch
*/
/**
 * @private
 * sends events to the 'boss' object
 **/
UA.Request.prototype.dispatch = function request_Dispatch(retObj, arrHandlers, sEventName){
	if(arrHandlers.length == 0){
		this.log.info(sEventName + ' from ' + this.toString() + ' contained no handlers.');
		return;
	}
	this.log.info('Dispatching ' + sEventName + ' from ' + this.toString());

	var i, cb;
	for (i = 0; i <  arrHandlers.length; i++){
		cb = arrHandlers[i];
		if (cb && typeof(cb) == 'function'){
			cb.call(this.boss, retObj, this.parameters);
		}
	}
}

/*    public methods	*/
//-------------------------------------------------------------
/*
	-- toString()
	-- onSuccess(request)
	-- onFailure(request)
	-- onTimeout(request)
	-- apply()
*/
/**
 * Overrides Object.toString
 **/
UA.Request.prototype.toString = function(){
	return "[UA.Request(" + this.id + ")] of " + this.boss.toString();
}

/**
 * The Jast.Request invokes this 3 calls when its call succeeds|fails|times-out.
 * The method passes the call to Game isntance that created it.
 *
 * @param {Jast.Request} request
 *  The request object that is passed to the handler.
 **/
UA.Request.prototype.onSuccess = function(request){
	this.dispatch(request.result.Data, this.successCallbacks, "onSuccess");
}
UA.Request.prototype.onFailure = function(request){
    this.log.error("Failed on request of: " + this.boss.toString() + " to url: " + this.urlWithParams + ", Status: " + request.result.Status );
	this.dispatch(request.result, this.failiorCallbacks, "onFailure");
}
UA.Request.prototype.onTimeout = function(request){
    this.log.error("Timeout on request of: " + this.boss.toString() + " to url: " + this.urlWithParams );
	this.dispatch(request, this.timeoutCallbacks,"onTimeout");
}
/**
 * This method sends the request.
 **/
UA.Request.prototype.apply = function(){
	//single-shot mechanizm
	if (this.isSent) 
		return;
	this.isSent = true;

	var url = Url.appendParams(this.url, this.parameters);
	//url = prompt(url,url);
	this.urlWithParams = url;
	this._JAST = new Jast.Request( url, this );
}