/*
 * TAjax
 */
function TAjax() {
	var self = this;
	this.stack = {};
    $(window).bind('beforeunload', function () {
	    return self._proceedDocumentBeforeUnload();
    });
}

TAjax.prototype = {

	sendAJAXPostRequest: function (ajaxData, ajaxTimeout, ajaxAbortMessage) {
		return this.sendAJAXRequest('POST', ajaxData, ajaxTimeout, ajaxAbortMessage);
	},

	sendAJAXGetRequest: function (ajaxData, ajaxTimeout, ajaxAbortMessage) {
		return this.sendAJAXRequest('GET', ajaxData, ajaxTimeout, ajaxAbortMessage);
	},

    /*
     * Sends AJAX request to the server and receives the response
     */
    sendAJAXRequest: function (method, ajaxData, ajaxTimeout, ajaxAbortMessage) {
        var self    = this,
            stackID = self._pushToStack(ajaxAbortMessage),
            data;

	    // Prepare data for request (fix)
	    if (ajaxData.contentType && ajaxData.contentType=='application/json') {
		    data = new Array();
		    for (var i in ajaxData.params) {
		        data.push('"' + i + '":"' + ajaxData.params[i].replace(/"/g, '\\"') + '"');
		    }
		    data = '{' + data.join(',') + '}';
		    ajaxData.processData = false;
	    }
	    else
	        data = ajaxData.params;

        var params = {
            url        : ajaxData.url,
            type       : method,
            data       : data,
            timeout    : ajaxTimeout,
            cache      : ajaxData.cache ? ajaxData.cache : false,
            processData: ajaxData.processData ? ajaxData.processData : true,
            async      : (ajaxData.async != undefined) ? ajaxData.async : true,
            success    : function (msg)
            {
                 self._popFromStack(stackID);
                 if (ajaxData.plainTextResponse) {
                     ajaxData.callbackAnswerOk(msg);
                 }
                 else {
                     var JSONobj = self._getJSONResponse(msg);
                     if (JSONobj) {
                         if (JSONobj.errors) {
                             // Callback on response ok, but the answer has errors
                             if (ajaxData.callbackAnswerHasErrors)
                                 ajaxData.callbackAnswerHasErrors(JSONobj);
                         }
                         else {
                             // Callback on response ok, answer has no errors
                             if (ajaxData.callbackAnswerOk)
                                 ajaxData.callbackAnswerOk(JSONobj);
                         }
                         // Callback on request over
                         if (ajaxData.callbackEndRequest)
                             ajaxData.callbackEndRequest(JSONobj);
                     }
                     else {
                         if (ajaxData.callbackServerError)
                             ajaxData.callbackServerError();

                         // Callback on request over
                         if (ajaxData.callbackEndRequest)
                             ajaxData.callbackEndRequest(null);
                     }
                 }
                 delete ajaxData;
             },
            error: function (errorResponse)
            {
                //setTimeout(function () { httpReq.abort(); }, 0);
                self._popFromStack(stackID);
                 // Server error callback (timeout is exceeded or another error happened)
                 if (ajaxData.callbackServerError)
                     ajaxData.callbackServerError(errorResponse);
                 // Callback on request over
                 if (ajaxData.callbackEndRequest)
                     ajaxData.callbackEndRequest(null);
                 delete ajaxData;
             }
        };

	    if (ajaxData.contentType)
		    params.contentType = ajaxData.contentType;
	    if (ajaxData.dataType)
		    params.dataType = ajaxData.dataType;
	    return $.ajax(params);
    },


    /*
     * Returns JSON object extracted from received data from the server
     */
    _getJSONResponse: function (data) {
        if (typeof(data) == 'object')
            return data;
        if (data.toString().toLowerCase().indexOf('<html')!=-1) {
            this.BREAK_AJAX = 1;
            if (location.search.toString().indexOf('debug=1')!=-1)
                document.body.innerHTML = '<textarea>'+data+'</textarea>';
            else {
	            // todo: proceed error here
            }
            return null;
        }
	    var JSONobj = $.getJSON(data);
	    if (JSONobj && JSONobj.system_error) {
	        this.BREAK_AJAX = 1;
	        return null;
	    }
	    else
		    return JSONobj;
    },


    // Pushes message to AJAX stack
    _pushToStack: function (msg) {
        if (msg) {
			var d  = new Date(),
				id = d.getMinutes().toString()+d.getSeconds().toString()+d.getMilliseconds().toString();
			this.stack[id] = msg;
			for (var id in this.stack) {
				return id;
			}
        }
	    else
	        return null;
    },

    // Pops message from AJAX stack
    _popFromStack: function (id) {
        if (id in this.stack) {
            var msg = this.stack[id];
            delete this.stack[id];
            return msg;
        }
        else
            return null;
    },

    // Returns the last message from AJAX stack
    _getFirstStackMessage: function () {
        for (var id in this.stack) {
            return this.stack[id];
        }
        return null;
    },

    _proceedDocumentBeforeUnload: function () {
        // Show confirmation dialog when user tries to close the browser window and anyone AJAX request is in a process.
        // In other case DO NOT RETURN ANYTHING to avoid showing of standard confirmation dialog.
	    if (this._getFirstStackMessage() && !this.BREAK_AJAX)
            return this._getFirstStackMessage() + '\nЕсли вы уйдете сейчас со страницы, данные могут быть утеряны.';
    }
};