var AjaxApp = Class.create({
	initialize: function(options) {
		this.options = $H({
			baseUrl: '/xml',
			pageLoader: null
		}).update(options || {});

		this.requestnumber = Math.floor(Math.random() * 1000000); // 0 - 999999
		this.queue = $H();

		this.busy = 0;
		this.requestCounter = 0;
		this.requests = $H();
	},

	/**
	 * Action is the action string and parameters object are send to the server. The options
	 * contains JS options.
	 *
	 */
	enqueue: function(action, parameters, myoptions) {
		var options = $H({
			element: null,
			actionBefore: null,
			action: null,
			actionAfter: null
		}).update(myoptions || {});

		this.queue.set(++this.requestnumber, { action: action, parameters: parameters, options: options });
	},

	processQueue: function() {
		var queue = this.queue.clone();
		this.clearQueue();

		var parameters = [];
		queue.each(function(pair) {
			var func = pair.value.options.get('actionBefore');
			// alert(func);
			if(!Object.isUndefined(func) && func!=null) {
				var element = $(pair.value.options.get('element'));
				if (Object.isFunction(func)) {
					func(element);
				}
				else if (Object.isArray(func)) {
					for(var f=0,lenf=func.length;f<lenf;++f) {
						func[f](element);
					}
				}
			}

			parameters[parameters.length] = { number: pair.key, action: pair.value.action, parameters: pair.value.parameters };
		}.bind(this));

		this.requestCounter++;
		var request = new Ajax.Request(this.options.get('baseUrl'), {
			method: 'post',
			parameters: { request: Object.toJSON(parameters) },
			onLoading: this.ajaxOnLoading.bind(this, this.requestCounter),
			onSuccess: this.actionCallback.bind(this, queue),
			onComplete: this.ajaxOnComplete.bind(this, this.requestCounter)
		});

		this.requests.set(this.requestCounter, request);

		return this.requestCounter;
	},

	clearQueue: function() {
		this.queue = $H();
	},

	cancel: function(requestid) {
		var request = this.requests.get(requestid);
		if (!Object.isUndefined(request)) {
			request.transport.abort();
			this.requests.unset(requestid);
		}
	},

	ajaxOnLoading: function(requestid) {
		this.busy++; 
		if (this.busy > 0 && this.options.get('pageLoader')) $(this.options.get('pageLoader')).show();
	},

	ajaxOnComplete: function(requestid) {
		this.busy--; 
		if (this.busy == 0 && this.options.get('pageLoader')) $(this.options.get('pageLoader')).hide();

		var request = this.requests.get(requestid);
		if (!Object.isUndefined(request)) {
			this.requests.unset(requestid); // remove from running requests
		}
	},

	actionCallback: function(queue, transport) {
		var errors = transport.responseJSON.errors;
		var responses = transport.responseJSON.response;

		var response;
		var responseNumber;
		var queuedItem;
		var element, actionFunc;
		var actions;

		for(var i=0,lenr=responses.length;i<lenr;++i) {
			response = responses[i];
			// responseNumber = response.number;

			queuedItem = queue.get(response.number);

			if (!Object.isUndefined(queuedItem)) {
				element = $(queuedItem.options.get('element'));
				actionFunc = queuedItem.options.get('action');

				actions = response.actions;

				for(var j=0,lena=actions.length;j<lena;++j) {
					switch(actions[j].actionType) {
						case 'content':
							if (!Object.isUndefined(element) && element!=null) {
								element.update(actions[j].content);
							}
							break;
						case 'value':
							if (actionFunc != null) {
								actionFunc(actions[j].value);
							}
							break;
						case 'script':
							// var func = actions[j].script;
							// func(element);
				eval(actions[j].script);
							break;
			case 'debug':
				var tmp = $('debug');
				if (!Object.isElement(tmp)) {
					var tmp = new Element('div', {'id': 'debug'});
				$$('body')[0].appendChild(tmp);
				}
				tmp.update(actions[j].content);
				break;
						case 'property':
							element.writeAttribute(actions[j].property, actions[j].value);
							break;
						default:
							// alert('unknown ' + actions[j].actionType);
							break;
					}
				}

				var func = queuedItem.options.get('actionAfter');
				if(!Object.isUndefined(func) && func!=null) {
					if (Object.isFunction(func)) {
						func(element);
					}
					else if (Object.isArray(func)) {
						for(var f=0,lenf=func.length;f<lenf;++f) {
							func[f](element);
						}
					}
				}
			}
		}
	}
});

