/**
 * @author Administrator
 */
(function($) {
    $.extend({
        manageAjax: function(o){
          o = $.extend({manageType: 'normal',maxReq: 0, blockSameRequest: false},o);
          return new $.ajaxManager(o);
        },
        ajaxManager: function(o){
            this.opt = o;
            this.queue = [];
        }
	});
    $.extend(
        $.ajaxManager.prototype,
        {
            add: function(o){
                 var quLen = this.queue.length, s = this.opt, q = this.queue, self = this,i,j;
                 var cD = (o.data && typeof o.data != "string")?$.param(o.data):o.data;
                 if(s.blockSameRequest){
                    var toPrevent = false;
                    for (var i = 0;i<quLen; i++){
                        if(q[i] && q[i].data === cD && q[i].url === o.url && q[i].type === o.type) {
                            toPrevent = true;
                            break;
                        }
                    }
                    if(toPrevent)
                        return false;
                 }
                 q[ quLen ] = {
            		fnError: o.error,
            		fnSuccess: o.success,
            		fnComplete: o.complete,
                    fnAbort: o.abort,
            		error: [],
            		success: [],
            		complete: [],
            		done: false,
            		queued: false,
                    data: cD,
                    url: o.url,
                    type: o.type,
                    xhr: null
            	};
                
                o.error = function(){if(q[ quLen ]) q[ quLen ].error = arguments; };
            	o.success = function(){if(q[ quLen ]) q[ quLen ].success = arguments; };
                o.abort = function(){if(q[ quLen ]) q[ quLen ].abort = arguments; };
                function startCallbacks(num){
                    if ( q[ num ].fnError ) q[ num ].fnError.apply( $, q[ num ].error );
        			if ( q[ num ].fnSuccess ) q[ num ].fnSuccess.apply( $, q[ num ].success );
        			if ( q[ num ].fnComplete ) q[ num ].fnComplete.apply( $, q[ num ].complete );
        			self.abort(num,true);
                }
                
            	o.complete = function(){
            		if(!q[ quLen ])
                        return;
                    q[ quLen ].complete = arguments;
            		q[ quLen ].done = true;
                    switch (s.manageType) {
                      case 'sync':
                        if (quLen === 0 || !q[ quLen-1 ]){
                            var curQLen = q.length;
                			for ( i = quLen; i < curQLen; i++ ) {
                                if(q[i]){
                                    if(q[i].done) 
                                        startCallbacks(i)
                                    else
                                        break;
                                }
                                
                			}
                        }
                        break;
                        case 'queue':
                        if (quLen === 0 || !q[ quLen-1 ]){
                            var curQLen = q.length;
                			for ( i = 0, j = 0; i < curQLen; i++ ) {
                                if(q[i] && q[i].queued){
                                    q[i].xhr = jQuery.ajax(q[i].xhr);
                                    q[i].queued = false;
                                    break;
                                }
                			}
                        }
                        startCallbacks(quLen);
                        break;
                      case 'abortOld':
                        startCallbacks(quLen);
                        for ( i = quLen; i >= 0; i-- ) {
                            if(q[i]){
                                self.abort(i);
                            }
            			}
                        break;
                      default:
                        startCallbacks(quLen);
                        break;
                    }
            	};
                
                if(s.maxReq){
                    if(s.manageType != 'queue') {
                        for (i = quLen, j = 0; i >= 0; i--) {
            				if(j >= s.maxReq)
                                this.abort(i);   
                            if(q[i]){
                                j++;
                            }   
            			}
                    } else {
                        for (i = 0, j = 0; i <= quLen && !q[quLen].queued; i++) {
                            if(q[i] && !q[i].queued)
                                j++;
                            if(j > s.maxReq)
                                q[quLen].queued = true;
            			}
                    }
                }
                q[ quLen ].xhr = (q[quLen].queued)?o:jQuery.ajax(o);
                return quLen;
            },
            cleanUp: function(){
               this.queue = [];
            },
            abort: function(num,completed){
               var qLen = this.queue.length, s = this.opt, q = this.queue, self = this,i;
               function del(num){
                   if(!q[num])
                       return;
                   (!completed && q[num].fnAbort) && q[num].fnAbort.apply($,[num]);
                   if(!q[num])
                       return;
                   if(q[num].xhr){
                      if (typeof q[num].xhr.abort != 'undefined') 
                          q[num].xhr.abort();
                      if (typeof q[num].xhr.close != 'undefined') 
                          q[num].xhr.close();
                      q[num].xhr = null;
                   }  
                    q[num] = null;
               }
               if(!num && num !== 0){
                   for (i = 0; i < qLen; i++){
                       del(i);
                   }
                   this.cleanUp();
               } else {
                   del(num);
                   var allowCleaning = true;
                   for (i = qLen; i >= 0; i--){
                       if(q[i]){
                            allowCleaning = false;
                            break;
                       }
                   }
                   if (allowCleaning) this.cleanUp(); 
               }
            }
        }
	);
})(jQuery);