/*
* Common.Ajax plugin
* -----------------------
* @author        : Filatov Dmitry <alpha@design.ru>
* @last_modified : 13.12.2007
*/

Common.Ajax = {

	READY_STATE_UNITIALIZED : 0,
	READY_STATE_LOADING     : 1,
	READY_STATE_LOADED      : 2,
	READY_STATE_INTERACTIVE : 3,
	READY_STATE_COMPLETE    : 4,

	getTransport : function() {

		if(window.XMLHttpRequest) {
			return new XMLHttpRequest();
		}

		if(window.ActiveXObject) {

			try {
				return new ActiveXObject('Msxml2.XMLHTTP');
			}
			catch(oException) {
				return new ActiveXObject('Microsoft.XMLHTTP');
			}

		}

		return null;

	},

	generateId : function() {

		var sId = '';

		for(var i = 0; i < 4; i++) {
			sId += (i > 0? '-' : '') + Math.floor(Math.random() * 9999);
		}

		return sId;

	},

	encodeForRequest : function(sText) {

		return escape(Common.Ajax.encodeUTF8(sText));

	},

	encodeUTF8 : function(sText) {

		sText = sText.replace(/\r\n/g, '\n');

		var sResult = "";

		for(var i = 0, sCharCode; i < sText.length; i++) {

			sCharCode = sText.charCodeAt(i);

			if(sCharCode < 128) {
				sResult += String.fromCharCode(sCharCode);
			}
			else if((sCharCode > 127) && (sCharCode < 2048)) {

				sResult += String.fromCharCode((sCharCode >> 6) | 192);
				sResult += String.fromCharCode((sCharCode & 63) | 128);

			}
			else {

				sResult += String.fromCharCode((sCharCode >> 12) | 224);
				sResult += String.fromCharCode(((sCharCode >> 6) & 63) | 128);
				sResult += String.fromCharCode((sCharCode & 63) | 128);

			}

		}

		return sResult;

	},

	Helper : function(
		sUrl,
		fSuccessCallback,
		fErrorCallback,
		aParams,
		oOptions
		) {

		this.sUrl = sUrl;
		this.fSuccessCallback = fSuccessCallback;
		this.fErrorCallback = fErrorCallback;
		this.aParams = aParams || [];
		this.oRequest = null;

		this.oOptions = Common.Object.extend(
			{
				bIgnoreCache : true,
				sMethod      : 'POST'
			},
			oOptions,
			true
			);

	}

}

Common.Ajax.Helper.prototype = {

	send : function() {

		var
			sQueryParams = '',
			iParamsCount = 0,
			sId = Common.Ajax.generateId()
			;

		this.aParams.foreach(function(mKey, mParam) {
			sQueryParams += (++iParamsCount == 1? '' : '&') + mKey + '=' + Common.Ajax.encodeForRequest(mParam);
		});

		this.oRequest = Common.Ajax.getTransport();

		if(this.oRequest) {

			this.oRequest.open(
				this.oOptions.sMethod,
				this.sUrl + (this.oOptions.bIgnoreCache? '?uid=' + sId : ''),
				true
				);

			this.oRequest.setRequestHeader(
				'Content-type',
				'application/x-www-form-urlencoded'
				);

			this.oRequest.setRequestHeader('Content-length', sQueryParams.length);
      		this.oRequest.setRequestHeader('Connection', 'close');

			var oThis = this;

			this.oRequest.onreadystatechange = function() {

				oThis.handleResponse();

			}

			this.oRequest.send(sQueryParams);

			return sId;

		}

	},

	handleResponse : function() {

		var fCallback = null;

		try {

			if(this.oRequest.readyState != Common.Ajax.READY_STATE_COMPLETE) {
				return;
			}

			if(this.success()) {
				if(this.fSuccessCallback) {
					fCallback = this.fSuccessCallback;
				}
			}
			else if(this.fErrorCallback) {
				fCallback = this.fErrorCallback;
			}

		}
		catch(oException) {};

		if(fCallback instanceof Function) {
			fCallback(this.oRequest);
		}

		this.oRequest.onreadystatechange = function() {};

	},

	success : function() {

		return this.oRequest &&
			(
				this.oRequest.status == 0 ||
				(this.oRequest.status >= 200 && this.oRequest.status < 300)
			)
			;

	}

}